"ezyang/htmlpurifier": "^4.10",
"masterminds/html5": "^2.6",
"mf2/mf2": "^0.4.6",
- "openid/php-openid": "^2.3"
+ "openid/php-openid": "^2.3",
+ "michelf/php-markdown": "^1.8.0",
+ "paragonie/constant_time_encoding": "^1.0.4",
+ "stomp-php/stomp-php": "^4.5.1",
+ "phpseclib/phpseclib": "^2.0.19",
+ "diogocomposer/xmpphp": "^3.0",
+ "apereo/phpcas": "^1.3"
},
"require-dev": {
"phpdocumentor/phpdocumentor": "^2.9",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "36b1e5eb69507ed41082369ded69837c",
+ "content-hash": "dea0804dd9970a97dcd17a53410327a0",
"packages": [
+ {
+ "name": "apereo/phpcas",
+ "version": "1.3.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/apereo/phpCAS.git",
+ "reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/apereo/phpCAS/zipball/b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
+ "reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~3.7.10"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "source/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Joachim Fritschi",
+ "homepage": "https://wiki.jasig.org/display/~fritschi"
+ },
+ {
+ "name": "Adam Franco",
+ "homepage": "https://wiki.jasig.org/display/~adamfranco"
+ }
+ ],
+ "description": "Provides a simple API for authenticating users against a CAS server",
+ "homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
+ "keywords": [
+ "apereo",
+ "cas",
+ "jasig"
+ ],
+ "time": "2019-04-22T19:48:16+00:00"
+ },
+ {
+ "name": "diogocomposer/xmpphp",
+ "version": "v3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/diogogithub/xmpphp.git",
+ "reference": "c7cdcc588aa47893ab41a1670c5dfe649674a4b0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/diogogithub/xmpphp/zipball/c7cdcc588aa47893ab41a1670c5dfe649674a4b0",
+ "reference": "c7cdcc588aa47893ab41a1670c5dfe649674a4b0",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "php": ">=7.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "XMPPHP\\": "XMPPHP"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Ivan Borzenkov",
+ "email": "ivan.borzenkov@gmail.com"
+ },
+ {
+ "name": "bandroidx",
+ "email": "bandroidx@gmail.com"
+ },
+ {
+ "name": "BirknerAlex",
+ "email": "alex.birkner@gmail.com"
+ },
+ {
+ "name": "Stephan Wentz",
+ "email": "stephan@wentz.it"
+ },
+ {
+ "name": "Nathan Fritz",
+ "email": "fritzy@netflint.net"
+ },
+ {
+ "name": "Christian Weiske",
+ "email": "cweiske@cweiske.de"
+ },
+ {
+ "name": "Vito Tafuni",
+ "email": "vitotafuni@gmail.com"
+ },
+ {
+ "name": "Diogo Cordeiro",
+ "email": "diogo@fc.up.pt"
+ }
+ ],
+ "description": "XMPP PHP Library",
+ "keywords": [
+ "jabber",
+ "xmpp",
+ "xmpphp"
+ ],
+ "time": "2019-06-19T02:32:32+00:00"
+ },
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
],
"time": "2018-08-24T14:47:04+00:00"
},
+ {
+ "name": "michelf/php-markdown",
+ "version": "1.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/michelf/php-markdown.git",
+ "reference": "01ab082b355bf188d907b9929cd99b2923053495"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495",
+ "reference": "01ab082b355bf188d907b9929cd99b2923053495",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Michelf\\": "Michelf/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Michel Fortin",
+ "email": "michel.fortin@michelf.ca",
+ "homepage": "https://michelf.ca/",
+ "role": "Developer"
+ },
+ {
+ "name": "John Gruber",
+ "homepage": "https://daringfireball.net/"
+ }
+ ],
+ "description": "PHP Markdown",
+ "homepage": "https://michelf.ca/projects/php-markdown/",
+ "keywords": [
+ "markdown"
+ ],
+ "time": "2018-01-15T00:49:33+00:00"
+ },
{
"name": "openid/php-openid",
"version": "2.3.0",
"yadis"
],
"time": "2015-07-30T18:07:43+00:00"
+ },
+ {
+ "name": "paragonie/constant_time_encoding",
+ "version": "v1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
+ "reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
+ "reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3|^7"
+ },
+ "require-dev": {
+ "paragonie/random_compat": "^1.4|^2",
+ "phpunit/phpunit": "4.*|5.*",
+ "vimeo/psalm": "^0.3|^1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base16",
+ "base32",
+ "base32_decode",
+ "base32_encode",
+ "base64",
+ "base64_decode",
+ "base64_encode",
+ "bin2hex",
+ "encoding",
+ "hex",
+ "hex2bin",
+ "rfc4648"
+ ],
+ "time": "2018-04-30T17:57:16+00:00"
+ },
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "2.0.19",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "d2085db7b7394baa071a69c8f9159723c250f2ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d2085db7b7394baa071a69c8f9159723c250f2ba",
+ "reference": "d2085db7b7394baa071a69c8f9159723c250f2ba",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phing/phing": "~2.7",
+ "phpunit/phpunit": "^4.8.35|^5.7|^6.0",
+ "sami/sami": "~2.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "suggest": {
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "homepage": "http://phpseclib.sourceforge.net",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ],
+ "time": "2019-06-20T03:34:11+00:00"
+ },
+ {
+ "name": "stomp-php/stomp-php",
+ "version": "4.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/stomp-php/stomp-php.git",
+ "reference": "4c5f0a95330085a86fd852b8ad0b1fbb4e8a4158"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/stomp-php/stomp-php/zipball/4c5f0a95330085a86fd852b8ad0b1fbb4e8a4158",
+ "reference": "4c5f0a95330085a86fd852b8ad0b1fbb4e8a4158",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Stomp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Dejan Bosnanac",
+ "email": "dejan@nighttale.net",
+ "homepage": "http://www.nighttale.net"
+ },
+ {
+ "name": "Sören Rohweder",
+ "email": "s.rohweder@blage.net",
+ "homepage": "http://www.monofone.de"
+ },
+ {
+ "name": "Jens Radtke",
+ "email": "swefl@fin-sn.de",
+ "homepage": "http://www.fin-sn.de"
+ }
+ ],
+ "description": "stomp support for PHP",
+ "homepage": "http://github.com/stomp-php/stomp-php",
+ "keywords": [
+ "activeMQ",
+ "apollomq",
+ "jms",
+ "messaging",
+ "rabbitmq",
+ "stomp"
+ ],
+ "time": "2019-04-09T08:25:54+00:00"
}
],
"packages-dev": [
+++ /dev/null
-<?php\r
-\r
-/*\r
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.\r
- * All rights reserved.\r
- * \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * \r
- * * Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the following disclaimer.\r
- * * Redistributions in binary form must reproduce the above copyright notice,\r
- * this list of conditions and the following disclaimer in the documentation\r
- * and/or other materials provided with the distribution.\r
- * * Neither the name of the ESUP-Portail consortium & the JA-SIG\r
- * Collaborative nor the names of its contributors may be used to endorse or\r
- * promote products derived from this software without specific prior\r
- * written permission.\r
-\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-//\r
-// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI'] in IIS\r
-//\r
-if (!$_SERVER['REQUEST_URI']) {\r
- $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];\r
-}\r
-\r
-//\r
-// another one by Vangelis Haniotakis also to make phpCAS work with PHP5\r
-//\r
-if (version_compare(PHP_VERSION, '5', '>=') && !(function_exists('domxml_new_doc'))) {\r
- require_once (dirname(__FILE__) . '/CAS/domxml-php4-to-php5.php');\r
-}\r
-\r
-/**\r
- * @file CAS/CAS.php\r
- * Interface class of the phpCAS library\r
- *\r
- * @ingroup public\r
- */\r
-\r
-// ########################################################################\r
-// CONSTANTS\r
-// ########################################################################\r
-\r
-// ------------------------------------------------------------------------\r
-// CAS VERSIONS\r
-// ------------------------------------------------------------------------\r
-\r
-/**\r
- * phpCAS version. accessible for the user by phpCAS::getVersion().\r
- */\r
-define('PHPCAS_VERSION', '1.1.2');\r
-\r
-// ------------------------------------------------------------------------\r
-// CAS VERSIONS\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup public\r
- * @{\r
- */\r
-\r
-/**\r
- * CAS version 1.0\r
- */\r
-define("CAS_VERSION_1_0", '1.0');\r
-/*!\r
- * CAS version 2.0\r
- */\r
-define("CAS_VERSION_2_0", '2.0');\r
-\r
-// ------------------------------------------------------------------------\r
-// SAML defines\r
-// ------------------------------------------------------------------------\r
-\r
-/**\r
- * SAML protocol\r
- */\r
-define("SAML_VERSION_1_1", 'S1');\r
-\r
-/**\r
- * XML header for SAML POST\r
- */\r
-define("SAML_XML_HEADER", '<?xml version="1.0" encoding="UTF-8"?>');\r
-\r
-/**\r
- * SOAP envelope for SAML POST\r
- */\r
-define("SAML_SOAP_ENV", '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/>');\r
-\r
-/**\r
- * SOAP body for SAML POST\r
- */\r
-define("SAML_SOAP_BODY", '<SOAP-ENV:Body>');\r
-\r
-/**\r
- * SAMLP request\r
- */\r
-define("SAMLP_REQUEST", '<samlp:Request xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" MajorVersion="1" MinorVersion="1" RequestID="_192.168.16.51.1024506224022" IssueInstant="2002-06-19T17:03:44.022Z">');\r
-define("SAMLP_REQUEST_CLOSE", '</samlp:Request>');\r
-\r
-/**\r
- * SAMLP artifact tag (for the ticket)\r
- */\r
-define("SAML_ASSERTION_ARTIFACT", '<samlp:AssertionArtifact>');\r
-\r
-/**\r
- * SAMLP close\r
- */\r
-define("SAML_ASSERTION_ARTIFACT_CLOSE", '</samlp:AssertionArtifact>');\r
-\r
-/**\r
- * SOAP body close\r
- */\r
-define("SAML_SOAP_BODY_CLOSE", '</SOAP-ENV:Body>');\r
-\r
-/**\r
- * SOAP envelope close\r
- */\r
-define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');\r
-\r
-/**\r
- * SAML Attributes\r
- */\r
-define("SAML_ATTRIBUTES", 'SAMLATTRIBS');\r
-\r
-/** @} */\r
-/**\r
- * @addtogroup publicPGTStorage\r
- * @{\r
- */\r
-// ------------------------------------------------------------------------\r
-// FILE PGT STORAGE\r
-// ------------------------------------------------------------------------\r
-/**\r
- * Default path used when storing PGT's to file\r
- */\r
-define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", '/tmp');\r
-/**\r
- * phpCAS::setPGTStorageFile()'s 2nd parameter to write plain text files\r
- */\r
-define("CAS_PGT_STORAGE_FILE_FORMAT_PLAIN", 'plain');\r
-/**\r
- * phpCAS::setPGTStorageFile()'s 2nd parameter to write xml files\r
- */\r
-define("CAS_PGT_STORAGE_FILE_FORMAT_XML", 'xml');\r
-/**\r
- * Default format used when storing PGT's to file\r
- */\r
-define("CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT", CAS_PGT_STORAGE_FILE_FORMAT_PLAIN);\r
-// ------------------------------------------------------------------------\r
-// DATABASE PGT STORAGE\r
-// ------------------------------------------------------------------------\r
-/**\r
- * default database type when storing PGT's to database\r
- */\r
-define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE", 'mysql');\r
-/**\r
- * default host when storing PGT's to database\r
- */\r
-define("CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME", 'localhost');\r
-/**\r
- * default port when storing PGT's to database\r
- */\r
-define("CAS_PGT_STORAGE_DB_DEFAULT_PORT", '');\r
-/**\r
- * default database when storing PGT's to database\r
- */\r
-define("CAS_PGT_STORAGE_DB_DEFAULT_DATABASE", 'phpCAS');\r
-/**\r
- * default table when storing PGT's to database\r
- */\r
-define("CAS_PGT_STORAGE_DB_DEFAULT_TABLE", 'pgt');\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-// SERVICE ACCESS ERRORS\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup publicServices\r
- * @{\r
- */\r
-\r
-/**\r
- * phpCAS::service() error code on success\r
- */\r
-define("PHPCAS_SERVICE_OK", 0);\r
-/**\r
- * phpCAS::service() error code when the PT could not retrieve because\r
- * the CAS server did not respond.\r
- */\r
-define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1);\r
-/**\r
- * phpCAS::service() error code when the PT could not retrieve because\r
- * the response of the CAS server was ill-formed.\r
- */\r
-define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2);\r
-/**\r
- * phpCAS::service() error code when the PT could not retrieve because\r
- * the CAS server did not want to.\r
- */\r
-define("PHPCAS_SERVICE_PT_FAILURE", 3);\r
-/**\r
- * phpCAS::service() error code when the service was not available.\r
- */\r
-define("PHPCAS_SERVICE_NOT AVAILABLE", 4);\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-// LANGUAGES\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup publicLang\r
- * @{\r
- */\r
-\r
-define("PHPCAS_LANG_ENGLISH", 'english');\r
-define("PHPCAS_LANG_FRENCH", 'french');\r
-define("PHPCAS_LANG_GREEK", 'greek');\r
-define("PHPCAS_LANG_GERMAN", 'german');\r
-define("PHPCAS_LANG_JAPANESE", 'japanese');\r
-define("PHPCAS_LANG_SPANISH", 'spanish');\r
-define("PHPCAS_LANG_CATALAN", 'catalan');\r
-\r
-/** @} */\r
-\r
-/**\r
- * @addtogroup internalLang\r
- * @{\r
- */\r
-\r
-/**\r
- * phpCAS default language (when phpCAS::setLang() is not used)\r
- */\r
-define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH);\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-// DEBUG\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup publicDebug\r
- * @{\r
- */\r
-\r
-/**\r
- * The default directory for the debug file under Unix.\r
- */\r
-define('DEFAULT_DEBUG_DIR', '/tmp/');\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-// MISC\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup internalMisc\r
- * @{\r
- */\r
-\r
-/**\r
- * This global variable is used by the interface class phpCAS.\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_CLIENT'] = null;\r
-\r
-/**\r
- * This global variable is used to store where the initializer is called from \r
- * (to print a comprehensive error in case of multiple calls).\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_INIT_CALL'] = array (\r
- 'done' => FALSE,\r
- 'file' => '?',\r
- 'line' => -1,\r
- 'method' => '?'\r
-);\r
-\r
-/**\r
- * This global variable is used to store where the method checking\r
- * the authentication is called from (to print comprehensive errors)\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_AUTH_CHECK_CALL'] = array (\r
- 'done' => FALSE,\r
- 'file' => '?',\r
- 'line' => -1,\r
- 'method' => '?',\r
- 'result' => FALSE\r
-);\r
-\r
-/**\r
- * This global variable is used to store phpCAS debug mode.\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_DEBUG'] = array (\r
- 'filename' => FALSE,\r
- 'indent' => 0,\r
- 'unique_id' => ''\r
-);\r
-\r
-/** @} */\r
-\r
-// ########################################################################\r
-// CLIENT CLASS\r
-// ########################################################################\r
-\r
-// include client class\r
-include_once (dirname(__FILE__) . '/CAS/client.php');\r
-\r
-// ########################################################################\r
-// INTERFACE CLASS\r
-// ########################################################################\r
-\r
-/**\r
- * @class phpCAS\r
- * The phpCAS class is a simple container for the phpCAS library. It provides CAS\r
- * authentication for web applications written in PHP.\r
- *\r
- * @ingroup public\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * \internal All its methods access the same object ($PHPCAS_CLIENT, declared \r
- * at the end of CAS/client.php).\r
- */\r
-\r
-class phpCAS {\r
-\r
- // ########################################################################\r
- // INITIALIZATION\r
- // ########################################################################\r
-\r
- /**\r
- * @addtogroup publicInit\r
- * @{\r
- */\r
-\r
- /**\r
- * phpCAS client initializer.\r
- * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be\r
- * called, only once, and before all other methods (except phpCAS::getVersion()\r
- * and phpCAS::setDebug()).\r
- *\r
- * @param $server_version the version of the CAS server\r
- * @param $server_hostname the hostname of the CAS server\r
- * @param $server_port the port the CAS server is running on\r
- * @param $server_uri the URI the CAS server is responding on\r
- * @param $start_session Have phpCAS start PHP sessions (default true)\r
- *\r
- * @return a newly created CASClient object\r
- */\r
- function client($server_version, $server_hostname, $server_port, $server_uri, $start_session = true) {\r
- global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error($PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . $PHPCAS_INIT_CALL['file'] . ':' . $PHPCAS_INIT_CALL['line'] . ')');\r
- }\r
- if (gettype($server_version) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');\r
- }\r
- if (gettype($server_hostname) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');\r
- }\r
- if (gettype($server_port) != 'integer') {\r
- phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');\r
- }\r
- if (gettype($server_uri) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');\r
- }\r
-\r
- // store where the initializer is called from\r
- $dbg = phpCAS :: backtrace();\r
- $PHPCAS_INIT_CALL = array (\r
- 'done' => TRUE,\r
- 'file' => $dbg[0]['file'],\r
- 'line' => $dbg[0]['line'],\r
- 'method' => __CLASS__ . '::' . __FUNCTION__\r
- );\r
-\r
- // initialize the global object $PHPCAS_CLIENT\r
- $PHPCAS_CLIENT = new CASClient($server_version, FALSE /*proxy*/\r
- , $server_hostname, $server_port, $server_uri, $start_session);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * phpCAS proxy initializer.\r
- * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be\r
- * called, only once, and before all other methods (except phpCAS::getVersion()\r
- * and phpCAS::setDebug()).\r
- *\r
- * @param $server_version the version of the CAS server\r
- * @param $server_hostname the hostname of the CAS server\r
- * @param $server_port the port the CAS server is running on\r
- * @param $server_uri the URI the CAS server is responding on\r
- * @param $start_session Have phpCAS start PHP sessions (default true)\r
- *\r
- * @return a newly created CASClient object\r
- */\r
- function proxy($server_version, $server_hostname, $server_port, $server_uri, $start_session = true) {\r
- global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error($PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . $PHPCAS_INIT_CALL['file'] . ':' . $PHPCAS_INIT_CALL['line'] . ')');\r
- }\r
- if (gettype($server_version) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');\r
- }\r
- if (gettype($server_hostname) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');\r
- }\r
- if (gettype($server_port) != 'integer') {\r
- phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');\r
- }\r
- if (gettype($server_uri) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');\r
- }\r
-\r
- // store where the initialzer is called from\r
- $dbg = phpCAS :: backtrace();\r
- $PHPCAS_INIT_CALL = array (\r
- 'done' => TRUE,\r
- 'file' => $dbg[0]['file'],\r
- 'line' => $dbg[0]['line'],\r
- 'method' => __CLASS__ . '::' . __FUNCTION__\r
- );\r
-\r
- // initialize the global object $PHPCAS_CLIENT\r
- $PHPCAS_CLIENT = new CASClient($server_version, TRUE /*proxy*/\r
- , $server_hostname, $server_port, $server_uri, $start_session);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // DEBUGGING\r
- // ########################################################################\r
-\r
- /**\r
- * @addtogroup publicDebug\r
- * @{\r
- */\r
-\r
- /**\r
- * Set/unset debug mode\r
- *\r
- * @param $filename the name of the file used for logging, or FALSE to stop debugging.\r
- */\r
- function setDebug($filename = '') {\r
- global $PHPCAS_DEBUG;\r
-\r
- if ($filename != FALSE && gettype($filename) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $dbg (should be FALSE or the name of the log file)');\r
- }\r
-\r
- if (empty ($filename)) {\r
- if (preg_match('/^Win.*/', getenv('OS'))) {\r
- if (isset ($_ENV['TMP'])) {\r
- $debugDir = $_ENV['TMP'] . '/';\r
- } else\r
- if (isset ($_ENV['TEMP'])) {\r
- $debugDir = $_ENV['TEMP'] . '/';\r
- } else {\r
- $debugDir = '';\r
- }\r
- } else {\r
- $debugDir = DEFAULT_DEBUG_DIR;\r
- }\r
- $filename = $debugDir . 'phpCAS.log';\r
- }\r
-\r
- if (empty ($PHPCAS_DEBUG['unique_id'])) {\r
- $PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);\r
- }\r
-\r
- $PHPCAS_DEBUG['filename'] = $filename;\r
-\r
- phpCAS :: trace('START phpCAS-' . PHPCAS_VERSION . ' ******************');\r
- }\r
-\r
- /** @} */\r
- /**\r
- * @addtogroup internalDebug\r
- * @{\r
- */\r
-\r
- /**\r
- * This method is a wrapper for debug_backtrace() that is not available \r
- * in all PHP versions (>= 4.3.0 only)\r
- */\r
- function backtrace() {\r
- if (function_exists('debug_backtrace')) {\r
- return debug_backtrace();\r
- } else {\r
- // poor man's hack ... but it does work ...\r
- return array ();\r
- }\r
- }\r
-\r
- /**\r
- * Logs a string in debug mode.\r
- *\r
- * @param $str the string to write\r
- *\r
- * @private\r
- */\r
- function log($str) {\r
- $indent_str = ".";\r
- global $PHPCAS_DEBUG;\r
-\r
- if ($PHPCAS_DEBUG['filename']) {\r
- for ($i = 0; $i < $PHPCAS_DEBUG['indent']; $i++) {\r
- $indent_str .= '| ';\r
- }\r
- error_log($PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str . "\n", 3, $PHPCAS_DEBUG['filename']);\r
- }\r
-\r
- }\r
-\r
- /**\r
- * This method is used by interface methods to print an error and where the function\r
- * was originally called from.\r
- *\r
- * @param $msg the message to print\r
- *\r
- * @private\r
- */\r
- function error($msg) {\r
- $dbg = phpCAS :: backtrace();\r
- $function = '?';\r
- $file = '?';\r
- $line = '?';\r
- if (is_array($dbg)) {\r
- for ($i = 1; $i < sizeof($dbg); $i++) {\r
- if (is_array($dbg[$i])) {\r
- if ($dbg[$i]['class'] == __CLASS__) {\r
- $function = $dbg[$i]['function'];\r
- $file = $dbg[$i]['file'];\r
- $line = $dbg[$i]['line'];\r
- }\r
- }\r
- }\r
- }\r
- echo "<br />\n<b>phpCAS error</b>: <font color=\"FF0000\"><b>" . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . "</b></font> in <b>" . $file . "</b> on line <b>" . $line . "</b><br />\n";\r
- phpCAS :: trace($msg);\r
- phpCAS :: traceExit();\r
- exit ();\r
- }\r
-\r
- /**\r
- * This method is used to log something in debug mode.\r
- */\r
- function trace($str) {\r
- $dbg = phpCAS :: backtrace();\r
- phpCAS :: log($str . ' [' . basename($dbg[1]['file']) . ':' . $dbg[1]['line'] . ']');\r
- }\r
-\r
- /**\r
- * This method is used to indicate the start of the execution of a function in debug mode.\r
- */\r
- function traceBegin() {\r
- global $PHPCAS_DEBUG;\r
-\r
- $dbg = phpCAS :: backtrace();\r
- $str = '=> ';\r
- if (!empty ($dbg[2]['class'])) {\r
- $str .= $dbg[2]['class'] . '::';\r
- }\r
- $str .= $dbg[2]['function'] . '(';\r
- if (is_array($dbg[2]['args'])) {\r
- foreach ($dbg[2]['args'] as $index => $arg) {\r
- if ($index != 0) {\r
- $str .= ', ';\r
- }\r
- $str .= str_replace("\n", "", var_export($arg, TRUE));\r
- }\r
- }\r
- $str .= ') [' . basename($dbg[2]['file']) . ':' . $dbg[2]['line'] . ']';\r
- phpCAS :: log($str);\r
- $PHPCAS_DEBUG['indent']++;\r
- }\r
-\r
- /**\r
- * This method is used to indicate the end of the execution of a function in debug mode.\r
- *\r
- * @param $res the result of the function\r
- */\r
- function traceEnd($res = '') {\r
- global $PHPCAS_DEBUG;\r
-\r
- $PHPCAS_DEBUG['indent']--;\r
- $dbg = phpCAS :: backtrace();\r
- $str = '';\r
- $str .= '<= ' . str_replace("\n", "", var_export($res, TRUE));\r
- phpCAS :: log($str);\r
- }\r
-\r
- /**\r
- * This method is used to indicate the end of the execution of the program\r
- */\r
- function traceExit() {\r
- global $PHPCAS_DEBUG;\r
-\r
- phpCAS :: log('exit()');\r
- while ($PHPCAS_DEBUG['indent'] > 0) {\r
- phpCAS :: log('-');\r
- $PHPCAS_DEBUG['indent']--;\r
- }\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // INTERNATIONALIZATION\r
- // ########################################################################\r
- /**\r
- * @addtogroup publicLang\r
- * @{\r
- */\r
-\r
- /**\r
- * This method is used to set the language used by phpCAS. \r
- * @note Can be called only once.\r
- *\r
- * @param $lang a string representing the language.\r
- *\r
- * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH\r
- */\r
- function setLang($lang) {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($lang) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $lang (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setLang($lang);\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // VERSION\r
- // ########################################################################\r
- /**\r
- * @addtogroup public\r
- * @{\r
- */\r
-\r
- /**\r
- * This method returns the phpCAS version.\r
- *\r
- * @return the phpCAS version.\r
- */\r
- function getVersion() {\r
- return PHPCAS_VERSION;\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // HTML OUTPUT\r
- // ########################################################################\r
- /**\r
- * @addtogroup publicOutput\r
- * @{\r
- */\r
-\r
- /**\r
- * This method sets the HTML header used for all outputs.\r
- *\r
- * @param $header the HTML header.\r
- */\r
- function setHTMLHeader($header) {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($header) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $header (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setHTMLHeader($header);\r
- }\r
-\r
- /**\r
- * This method sets the HTML footer used for all outputs.\r
- *\r
- * @param $footer the HTML footer.\r
- */\r
- function setHTMLFooter($footer) {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($footer) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $footer (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setHTMLFooter($footer);\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // PGT STORAGE\r
- // ########################################################################\r
- /**\r
- * @addtogroup publicPGTStorage\r
- * @{\r
- */\r
-\r
- /**\r
- * This method is used to tell phpCAS to store the response of the\r
- * CAS server to PGT requests onto the filesystem. \r
- *\r
- * @param $format the format used to store the PGT's (`plain' and `xml' allowed)\r
- * @param $path the path where the PGT's should be stored\r
- */\r
- function setPGTStorageFile($format = '', $path = '') {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_CLIENT->isProxy()) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if ($PHPCAS_AUTH_CHECK_CALL['done']) {\r
- phpCAS :: error('this method should only be called before ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() (called at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ')');\r
- }\r
- if (gettype($format) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $format (should be `string\')');\r
- }\r
- if (gettype($path) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $format (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setPGTStorageFile($format, $path);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method is used to tell phpCAS to store the response of the\r
- * CAS server to PGT requests into a database. \r
- * @note The connection to the database is done only when needed. \r
- * As a consequence, bad parameters are detected only when \r
- * initializing PGT storage, except in debug mode.\r
- *\r
- * @param $user the user to access the data with\r
- * @param $password the user's password\r
- * @param $database_type the type of the database hosting the data\r
- * @param $hostname the server hosting the database\r
- * @param $port the port the server is listening on\r
- * @param $database the name of the database\r
- * @param $table the name of the table storing the data\r
- */\r
- function setPGTStorageDB($user, $password, $database_type = '', $hostname = '', $port = 0, $database = '', $table = '') {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_CLIENT->isProxy()) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if ($PHPCAS_AUTH_CHECK_CALL['done']) {\r
- phpCAS :: error('this method should only be called before ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() (called at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ')');\r
- }\r
- if (gettype($user) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $user (should be `string\')');\r
- }\r
- if (gettype($password) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $password (should be `string\')');\r
- }\r
- if (gettype($database_type) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $database_type (should be `string\')');\r
- }\r
- if (gettype($hostname) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $hostname (should be `string\')');\r
- }\r
- if (gettype($port) != 'integer') {\r
- phpCAS :: error('type mismatched for parameter $port (should be `integer\')');\r
- }\r
- if (gettype($database) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $database (should be `string\')');\r
- }\r
- if (gettype($table) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $table (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setPGTStorageDB($user, $password, $database_type, $hostname, $port, $database, $table);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // ACCESS TO EXTERNAL SERVICES\r
- // ########################################################################\r
- /**\r
- * @addtogroup publicServices\r
- * @{\r
- */\r
-\r
- /**\r
- * This method is used to access an HTTP[S] service.\r
- * \r
- * @param $url the service to access.\r
- * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on\r
- * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,\r
- * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.\r
- * @param $output the output of the service (also used to give an error\r
- * message on failure).\r
- *\r
- * @return TRUE on success, FALSE otherwise (in this later case, $err_code\r
- * gives the reason why it failed and $output contains an error message).\r
- */\r
- function serviceWeb($url, & $err_code, & $output) {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_CLIENT->isProxy()) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
- phpCAS :: error('this method should only be called after the programmer is sure the user has been authenticated (by calling ' . __CLASS__ . '::checkAuthentication() or ' . __CLASS__ . '::forceAuthentication()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
- phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
- }\r
-\r
- $res = $PHPCAS_CLIENT->serviceWeb($url, $err_code, $output);\r
-\r
- phpCAS :: traceEnd($res);\r
- return $res;\r
- }\r
-\r
- /**\r
- * This method is used to access an IMAP/POP3/NNTP service.\r
- * \r
- * @param $url a string giving the URL of the service, including the mailing box\r
- * for IMAP URLs, as accepted by imap_open().\r
- * @param $service a string giving for CAS retrieve Proxy ticket\r
- * @param $flags options given to imap_open().\r
- * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on\r
- * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,\r
- * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.\r
- * @param $err_msg an error message on failure\r
- * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL\r
- * on success, FALSE on error).\r
- *\r
- * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code\r
- * gives the reason why it failed and $err_msg contains an error message).\r
- */\r
- function serviceMail($url, $service, $flags, & $err_code, & $err_msg, & $pt) {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_CLIENT->isProxy()) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
- phpCAS :: error('this method should only be called after the programmer is sure the user has been authenticated (by calling ' . __CLASS__ . '::checkAuthentication() or ' . __CLASS__ . '::forceAuthentication()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
- phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
- }\r
-\r
- if (gettype($flags) != 'integer') {\r
- phpCAS :: error('type mismatched for parameter $flags (should be `integer\')');\r
- }\r
-\r
- $res = $PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt);\r
-\r
- phpCAS :: traceEnd($res);\r
- return $res;\r
- }\r
-\r
- /** @} */\r
- // ########################################################################\r
- // AUTHENTICATION\r
- // ########################################################################\r
- /**\r
- * @addtogroup publicAuth\r
- * @{\r
- */\r
-\r
- /**\r
- * Set the times authentication will be cached before really accessing the CAS server in gateway mode: \r
- * - -1: check only once, and then never again (until you pree login)\r
- * - 0: always check\r
- * - n: check every "n" time\r
- *\r
- * @param $n an integer.\r
- */\r
- function setCacheTimesForAuthRecheck($n) {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($n) != 'integer') {\r
- phpCAS :: error('type mismatched for parameter $header (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n);\r
- }\r
-\r
- /**\r
- * This method is called to check if the user is authenticated (use the gateway feature).\r
- * @return TRUE when the user is authenticated; otherwise FALSE.\r
- */\r
- function checkAuthentication() {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
-\r
- $auth = $PHPCAS_CLIENT->checkAuthentication();\r
-\r
- // store where the authentication has been checked and the result\r
- $dbg = phpCAS :: backtrace();\r
- $PHPCAS_AUTH_CHECK_CALL = array (\r
- 'done' => TRUE,\r
- 'file' => $dbg[0]['file'],\r
- 'line' => $dbg[0]['line'],\r
- 'method' => __CLASS__ . '::' . __FUNCTION__,\r
- 'result' => $auth\r
- );\r
- phpCAS :: traceEnd($auth);\r
- return $auth;\r
- }\r
-\r
- /**\r
- * This method is called to force authentication if the user was not already \r
- * authenticated. If the user is not authenticated, halt by redirecting to \r
- * the CAS server.\r
- */\r
- function forceAuthentication() {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
-\r
- $auth = $PHPCAS_CLIENT->forceAuthentication();\r
-\r
- // store where the authentication has been checked and the result\r
- $dbg = phpCAS :: backtrace();\r
- $PHPCAS_AUTH_CHECK_CALL = array (\r
- 'done' => TRUE,\r
- 'file' => $dbg[0]['file'],\r
- 'line' => $dbg[0]['line'],\r
- 'method' => __CLASS__ . '::' . __FUNCTION__,\r
- 'result' => $auth\r
- );\r
-\r
- if (!$auth) {\r
- phpCAS :: trace('user is not authenticated, redirecting to the CAS server');\r
- $PHPCAS_CLIENT->forceAuthentication();\r
- } else {\r
- phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)');\r
- }\r
-\r
- phpCAS :: traceEnd();\r
- return $auth;\r
- }\r
-\r
- /**\r
- * This method is called to renew the authentication.\r
- **/\r
- function renewAuthentication() {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
-\r
- // store where the authentication has been checked and the result\r
- $dbg = phpCAS :: backtrace();\r
- $PHPCAS_AUTH_CHECK_CALL = array (\r
- 'done' => TRUE,\r
- 'file' => $dbg[0]['file'],\r
- 'line' => $dbg[0]['line'],\r
- 'method' => __CLASS__ . '::' . __FUNCTION__,\r
- 'result' => $auth\r
- );\r
-\r
- $PHPCAS_CLIENT->renewAuthentication();\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method has been left from version 0.4.1 for compatibility reasons.\r
- */\r
- function authenticate() {\r
- phpCAS :: error('this method is deprecated. You should use ' . __CLASS__ . '::forceAuthentication() instead');\r
- }\r
-\r
- /**\r
- * This method is called to check if the user is authenticated (previously or by\r
- * tickets given in the URL).\r
- *\r
- * @return TRUE when the user is authenticated.\r
- */\r
- function isAuthenticated() {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
-\r
- // call the isAuthenticated method of the global $PHPCAS_CLIENT object\r
- $auth = $PHPCAS_CLIENT->isAuthenticated();\r
-\r
- // store where the authentication has been checked and the result\r
- $dbg = phpCAS :: backtrace();\r
- $PHPCAS_AUTH_CHECK_CALL = array (\r
- 'done' => TRUE,\r
- 'file' => $dbg[0]['file'],\r
- 'line' => $dbg[0]['line'],\r
- 'method' => __CLASS__ . '::' . __FUNCTION__,\r
- 'result' => $auth\r
- );\r
- phpCAS :: traceEnd($auth);\r
- return $auth;\r
- }\r
-\r
- /**\r
- * Checks whether authenticated based on $_SESSION. Useful to avoid\r
- * server calls.\r
- * @return true if authenticated, false otherwise.\r
- * @since 0.4.22 by Brendan Arnold\r
- */\r
- function isSessionAuthenticated() {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- return ($PHPCAS_CLIENT->isSessionAuthenticated());\r
- }\r
-\r
- /**\r
- * This method returns the CAS user's login name.\r
- * @warning should not be called only after phpCAS::forceAuthentication()\r
- * or phpCAS::checkAuthentication().\r
- *\r
- * @return the login name of the authenticated user\r
- */\r
- function getUser() {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
- phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
- }\r
- return $PHPCAS_CLIENT->getUser();\r
- }\r
-\r
- /**\r
- * This method returns the CAS user's login name.\r
- * @warning should not be called only after phpCAS::forceAuthentication()\r
- * or phpCAS::checkAuthentication().\r
- *\r
- * @return the login name of the authenticated user\r
- */\r
- function getAttributes() {\r
- global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');\r
- }\r
- if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
- phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
- }\r
- return $PHPCAS_CLIENT->getAttributes();\r
- }\r
- /**\r
- * Handle logout requests.\r
- */\r
- function handleLogoutRequests($check_client = true, $allowed_clients = false) {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- return ($PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients));\r
- }\r
-\r
- /**\r
- * This method returns the URL to be used to login.\r
- * or phpCAS::isAuthenticated().\r
- *\r
- * @return the login name of the authenticated user\r
- */\r
- function getServerLoginURL() {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- return $PHPCAS_CLIENT->getServerLoginURL();\r
- }\r
-\r
- /**\r
- * Set the login URL of the CAS server.\r
- * @param $url the login URL\r
- * @since 0.4.21 by Wyman Chan\r
- */\r
- function setServerLoginURL($url = '') {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after\r
- ' . __CLASS__ . '::client()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be\r
- `string\')');\r
- }\r
- $PHPCAS_CLIENT->setServerLoginURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set the serviceValidate URL of the CAS server.\r
- * Used only in CAS 1.0 validations\r
- * @param $url the serviceValidate URL\r
- * @since 1.1.0 by Joachim Fritschi\r
- */\r
- function setServerServiceValidateURL($url = '') {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after\r
- ' . __CLASS__ . '::client()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be\r
- `string\')');\r
- }\r
- $PHPCAS_CLIENT->setServerServiceValidateURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set the proxyValidate URL of the CAS server.\r
- * Used for all CAS 2.0 validations\r
- * @param $url the proxyValidate URL\r
- * @since 1.1.0 by Joachim Fritschi\r
- */\r
- function setServerProxyValidateURL($url = '') {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after\r
- ' . __CLASS__ . '::client()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be\r
- `string\')');\r
- }\r
- $PHPCAS_CLIENT->setServerProxyValidateURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set the samlValidate URL of the CAS server.\r
- * @param $url the samlValidate URL\r
- * @since 1.1.0 by Joachim Fritschi\r
- */\r
- function setServerSamlValidateURL($url = '') {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after\r
- ' . __CLASS__ . '::client()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be\r
- `string\')');\r
- }\r
- $PHPCAS_CLIENT->setServerSamlValidateURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method returns the URL to be used to login.\r
- * or phpCAS::isAuthenticated().\r
- *\r
- * @return the login name of the authenticated user\r
- */\r
- function getServerLogoutURL() {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
- }\r
- return $PHPCAS_CLIENT->getServerLogoutURL();\r
- }\r
-\r
- /**\r
- * Set the logout URL of the CAS server.\r
- * @param $url the logout URL\r
- * @since 0.4.21 by Wyman Chan\r
- */\r
- function setServerLogoutURL($url = '') {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after\r
- ' . __CLASS__ . '::client()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be\r
- `string\')');\r
- }\r
- $PHPCAS_CLIENT->setServerLogoutURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method is used to logout from CAS.\r
- * @params $params an array that contains the optional url and service parameters that will be passed to the CAS server\r
- * @public\r
- */\r
- function logout($params = "") {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- $parsedParams = array ();\r
- if ($params != "") {\r
- if (is_string($params)) {\r
- phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead');\r
- }\r
- if (!is_array($params)) {\r
- phpCAS :: error('type mismatched for parameter $params (should be `array\')');\r
- }\r
- foreach ($params as $key => $value) {\r
- if ($key != "service" && $key != "url") {\r
- phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\'');\r
- }\r
- $parsedParams[$key] = $value;\r
- }\r
- }\r
- $PHPCAS_CLIENT->logout($parsedParams);\r
- // never reached\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method is used to logout from CAS. Halts by redirecting to the CAS server.\r
- * @param $service a URL that will be transmitted to the CAS server\r
- */\r
- function logoutWithRedirectService($service) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- if (!is_string($service)) {\r
- phpCAS :: error('type mismatched for parameter $service (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->logout(array (\r
- "service" => $service\r
- ));\r
- // never reached\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method is used to logout from CAS. Halts by redirecting to the CAS server.\r
- * @param $url a URL that will be transmitted to the CAS server\r
- */\r
- function logoutWithUrl($url) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- if (!is_string($url)) {\r
- phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->logout(array (\r
- "url" => $url\r
- ));\r
- // never reached\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * This method is used to logout from CAS. Halts by redirecting to the CAS server.\r
- * @param $service a URL that will be transmitted to the CAS server\r
- * @param $url a URL that will be transmitted to the CAS server\r
- */\r
- function logoutWithRedirectServiceAndUrl($service, $url) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- if (!is_string($service)) {\r
- phpCAS :: error('type mismatched for parameter $service (should be `string\')');\r
- }\r
- if (!is_string($url)) {\r
- phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->logout(array (\r
- "service" => $service,\r
- "url" => $url\r
- ));\r
- // never reached\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set the fixed URL that will be used by the CAS server to transmit the PGT.\r
- * When this method is not called, a phpCAS script uses its own URL for the callback.\r
- *\r
- * @param $url the URL\r
- */\r
- function setFixedCallbackURL($url = '') {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (!$PHPCAS_CLIENT->isProxy()) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setCallbackURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set the fixed URL that will be set as the CAS service parameter. When this\r
- * method is not called, a phpCAS script uses its own URL.\r
- *\r
- * @param $url the URL\r
- */\r
- function setFixedServiceURL($url) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($url) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setURL($url);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Get the URL that is set as the CAS service parameter.\r
- */\r
- function getServiceURL() {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- return ($PHPCAS_CLIENT->getURL());\r
- }\r
-\r
- /**\r
- * Retrieve a Proxy Ticket from the CAS server.\r
- */\r
- function retrievePT($target_service, & $err_code, & $err_msg) {\r
- global $PHPCAS_CLIENT;\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($target_service) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $target_service(should be `string\')');\r
- }\r
- return ($PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg));\r
- }\r
-\r
- /**\r
- * Set the certificate of the CAS server.\r
- *\r
- * @param $cert the PEM certificate\r
- */\r
- function setCasServerCert($cert) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($cert) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $cert (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setCasServerCert($cert);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set the certificate of the CAS server CA.\r
- *\r
- * @param $cert the CA certificate\r
- */\r
- function setCasServerCACert($cert) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- if (gettype($cert) != 'string') {\r
- phpCAS :: error('type mismatched for parameter $cert (should be `string\')');\r
- }\r
- $PHPCAS_CLIENT->setCasServerCACert($cert);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /**\r
- * Set no SSL validation for the CAS server.\r
- */\r
- function setNoCasServerValidation() {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- $PHPCAS_CLIENT->setNoCasServerValidation();\r
- phpCAS :: traceEnd();\r
- }\r
-\r
- /** @} */\r
-\r
- /**\r
- * Change CURL options.\r
- * CURL is used to connect through HTTPS to CAS server\r
- * @param $key the option key\r
- * @param $value the value to set\r
- */\r
- function setExtraCurlOption($key, $value) {\r
- global $PHPCAS_CLIENT;\r
- phpCAS :: traceBegin();\r
- if (!is_object($PHPCAS_CLIENT)) {\r
- phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
- }\r
- $PHPCAS_CLIENT->setExtraCurlOption($key, $value);\r
- phpCAS :: traceEnd();\r
- }\r
-\r
-}\r
-\r
-// ########################################################################\r
-// DOCUMENTATION\r
-// ########################################################################\r
-\r
-// ########################################################################\r
-// MAIN PAGE\r
-\r
-/**\r
- * @mainpage\r
- *\r
- * The following pages only show the source documentation.\r
- *\r
- */\r
-\r
-// ########################################################################\r
-// MODULES DEFINITION\r
-\r
-/** @defgroup public User interface */\r
-\r
-/** @defgroup publicInit Initialization\r
- * @ingroup public */\r
-\r
-/** @defgroup publicAuth Authentication\r
- * @ingroup public */\r
-\r
-/** @defgroup publicServices Access to external services\r
- * @ingroup public */\r
-\r
-/** @defgroup publicConfig Configuration\r
- * @ingroup public */\r
-\r
-/** @defgroup publicLang Internationalization\r
- * @ingroup publicConfig */\r
-\r
-/** @defgroup publicOutput HTML output\r
- * @ingroup publicConfig */\r
-\r
-/** @defgroup publicPGTStorage PGT storage\r
- * @ingroup publicConfig */\r
-\r
-/** @defgroup publicDebug Debugging\r
- * @ingroup public */\r
-\r
-/** @defgroup internal Implementation */\r
-\r
-/** @defgroup internalAuthentication Authentication\r
- * @ingroup internal */\r
-\r
-/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets)\r
- * @ingroup internal */\r
-\r
-/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets)\r
- * @ingroup internal */\r
-\r
-/** @defgroup internalPGTStorage PGT storage\r
- * @ingroup internalProxy */\r
-\r
-/** @defgroup internalPGTStorageDB PGT storage in a database\r
- * @ingroup internalPGTStorage */\r
-\r
-/** @defgroup internalPGTStorageFile PGT storage on the filesystem\r
- * @ingroup internalPGTStorage */\r
-\r
-/** @defgroup internalCallback Callback from the CAS server\r
- * @ingroup internalProxy */\r
-\r
-/** @defgroup internalProxied CAS proxied client features (CAS 2.0, Proxy Tickets)\r
- * @ingroup internal */\r
-\r
-/** @defgroup internalConfig Configuration\r
- * @ingroup internal */\r
-\r
-/** @defgroup internalOutput HTML output\r
- * @ingroup internalConfig */\r
-\r
-/** @defgroup internalLang Internationalization\r
- * @ingroup internalConfig\r
- *\r
- * To add a new language:\r
- * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php\r
- * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php\r
- * - 3. Make the translations\r
- */\r
-\r
-/** @defgroup internalDebug Debugging\r
- * @ingroup internal */\r
-\r
-/** @defgroup internalMisc Miscellaneous\r
- * @ingroup internal */\r
-\r
-// ########################################################################\r
-// EXAMPLES\r
-\r
-/**\r
- * @example example_simple.php\r
- */\r
-/**\r
- * @example example_proxy.php\r
- */\r
-/**\r
- * @example example_proxy2.php\r
- */\r
-/**\r
- * @example example_lang.php\r
- */\r
-/**\r
- * @example example_html.php\r
- */\r
-/**\r
- * @example example_file.php\r
- */\r
-/**\r
- * @example example_db.php\r
- */\r
-/**\r
- * @example example_service.php\r
- */\r
-/**\r
- * @example example_session_proxy.php\r
- */\r
-/**\r
- * @example example_session_service.php\r
- */\r
-/**\r
- * @example example_gateway.php\r
- */\r
-/**\r
- * @example example_custom_urls.php\r
- */\r
-?>\r
+++ /dev/null
-<?php\r
-/*\r
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.\r
- * All rights reserved.\r
- * \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * \r
- * * Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the following disclaimer.\r
- * * Redistributions in binary form must reproduce the above copyright notice,\r
- * this list of conditions and the following disclaimer in the documentation\r
- * and/or other materials provided with the distribution.\r
- * * Neither the name of the ESUP-Portail consortium & the JA-SIG\r
- * Collaborative nor the names of its contributors may be used to endorse or\r
- * promote products derived from this software without specific prior\r
- * written permission.\r
-\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/**\r
- * @file CAS/PGTStorage/pgt-db.php\r
- * Basic class for PGT database storage\r
- */\r
-\r
-/**\r
- * @class PGTStorageDB\r
- * The PGTStorageDB class is a class for PGT database storage. An instance of \r
- * this class is returned by CASClient::SetPGTStorageDB().\r
- *\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * @ingroup internalPGTStorageDB\r
- */\r
-\r
-class PGTStorageDB extends PGTStorage\r
-{\r
- /** \r
- * @addtogroup internalPGTStorageDB\r
- * @{ \r
- */\r
-\r
- /**\r
- * a string representing a PEAR DB URL to connect to the database. Written by\r
- * PGTStorageDB::PGTStorageDB(), read by getURL().\r
- *\r
- * @hideinitializer\r
- * @private\r
- */\r
- var $_url='';\r
-\r
- /**\r
- * This method returns the PEAR DB URL to use to connect to the database.\r
- *\r
- * @return a PEAR DB URL\r
- *\r
- * @private\r
- */\r
- function getURL()\r
- {\r
- return $this->_url;\r
- }\r
-\r
- /**\r
- * The handle of the connection to the database where PGT's are stored. Written by\r
- * PGTStorageDB::init(), read by getLink().\r
- *\r
- * @hideinitializer\r
- * @private\r
- */\r
- var $_link = null;\r
-\r
- /**\r
- * This method returns the handle of the connection to the database where PGT's are \r
- * stored.\r
- *\r
- * @return a handle of connection.\r
- *\r
- * @private\r
- */\r
- function getLink()\r
- {\r
- return $this->_link;\r
- }\r
-\r
- /**\r
- * The name of the table where PGT's are stored. Written by \r
- * PGTStorageDB::PGTStorageDB(), read by getTable().\r
- *\r
- * @hideinitializer\r
- * @private\r
- */\r
- var $_table = '';\r
-\r
- /**\r
- * This method returns the name of the table where PGT's are stored.\r
- *\r
- * @return the name of a table.\r
- *\r
- * @private\r
- */\r
- function getTable()\r
- {\r
- return $this->_table;\r
- }\r
-\r
- // ########################################################################\r
- // DEBUGGING\r
- // ########################################################################\r
- \r
- /**\r
- * This method returns an informational string giving the type of storage\r
- * used by the object (used for debugging purposes).\r
- *\r
- * @return an informational string.\r
- * @public\r
- */\r
- function getStorageType()\r
- {\r
- return "database";\r
- }\r
-\r
- /**\r
- * This method returns an informational string giving informations on the\r
- * parameters of the storage.(used for debugging purposes).\r
- *\r
- * @public\r
- */\r
- function getStorageInfo()\r
- {\r
- return 'url=`'.$this->getURL().'\', table=`'.$this->getTable().'\'';\r
- }\r
-\r
- // ########################################################################\r
- // CONSTRUCTOR\r
- // ########################################################################\r
- \r
- /**\r
- * The class constructor, called by CASClient::SetPGTStorageDB().\r
- *\r
- * @param $cas_parent the CASClient instance that creates the object.\r
- * @param $user the user to access the data with\r
- * @param $password the user's password\r
- * @param $database_type the type of the database hosting the data\r
- * @param $hostname the server hosting the database\r
- * @param $port the port the server is listening on\r
- * @param $database the name of the database\r
- * @param $table the name of the table storing the data\r
- *\r
- * @public\r
- */\r
- function PGTStorageDB($cas_parent,$user,$password,$database_type,$hostname,$port,$database,$table)\r
- {\r
- phpCAS::traceBegin();\r
-\r
- // call the ancestor's constructor\r
- $this->PGTStorage($cas_parent);\r
-\r
- if ( empty($database_type) ) $database_type = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE_TYPE;\r
- if ( empty($hostname) ) $hostname = CAS_PGT_STORAGE_DB_DEFAULT_HOSTNAME;\r
- if ( $port==0 ) $port = CAS_PGT_STORAGE_DB_DEFAULT_PORT;\r
- if ( empty($database) ) $database = CAS_PGT_STORAGE_DB_DEFAULT_DATABASE;\r
- if ( empty($table) ) $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE;\r
-\r
- // build and store the PEAR DB URL\r
- $this->_url = $database_type.':'.'//'.$user.':'.$password.'@'.$hostname.':'.$port.'/'.$database;\r
-\r
- // XXX should use setURL and setTable\r
- phpCAS::traceEnd();\r
- }\r
- \r
- // ########################################################################\r
- // INITIALIZATION\r
- // ########################################################################\r
- \r
- /**\r
- * This method is used to initialize the storage. Halts on error.\r
- *\r
- * @public\r
- */\r
- function init()\r
- {\r
- phpCAS::traceBegin();\r
- // if the storage has already been initialized, return immediatly\r
- if ( $this->isInitialized() )\r
- return;\r
- // call the ancestor's method (mark as initialized)\r
- parent::init();\r
- \r
- //include phpDB library (the test was introduced in release 0.4.8 for \r
- //the integration into Tikiwiki).\r
- if (!class_exists('DB')) {\r
- include_once('DB.php');\r
- }\r
-\r
- // try to connect to the database\r
- $this->_link = DB::connect($this->getURL());\r
- if ( DB::isError($this->_link) ) {\r
- phpCAS::error('could not connect to database ('.DB::errorMessage($this->_link).')');\r
- }\r
- var_dump($this->_link);\r
- phpCAS::traceBEnd();\r
- }\r
-\r
- /** @} */\r
-}\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-/*\r
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.\r
- * All rights reserved.\r
- * \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * \r
- * * Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the following disclaimer.\r
- * * Redistributions in binary form must reproduce the above copyright notice,\r
- * this list of conditions and the following disclaimer in the documentation\r
- * and/or other materials provided with the distribution.\r
- * * Neither the name of the ESUP-Portail consortium & the JA-SIG\r
- * Collaborative nor the names of its contributors may be used to endorse or\r
- * promote products derived from this software without specific prior\r
- * written permission.\r
-\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-/**\r
- * @file CAS/PGTStorage/pgt-file.php\r
- * Basic class for PGT file storage\r
- */\r
-\r
-/**\r
- * @class PGTStorageFile\r
- * The PGTStorageFile class is a class for PGT file storage. An instance of \r
- * this class is returned by CASClient::SetPGTStorageFile().\r
- *\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * @ingroup internalPGTStorageFile\r
- */\r
-\r
-class PGTStorageFile extends PGTStorage\r
-{\r
- /** \r
- * @addtogroup internalPGTStorageFile \r
- * @{ \r
- */\r
-\r
- /**\r
- * a string telling where PGT's should be stored on the filesystem. Written by\r
- * PGTStorageFile::PGTStorageFile(), read by getPath().\r
- *\r
- * @private\r
- */\r
- var $_path;\r
-\r
- /**\r
- * This method returns the name of the directory where PGT's should be stored \r
- * on the filesystem.\r
- *\r
- * @return the name of a directory (with leading and trailing '/')\r
- *\r
- * @private\r
- */\r
- function getPath()\r
- {\r
- return $this->_path;\r
- }\r
-\r
- /**\r
- * a string telling the format to use to store PGT's (plain or xml). Written by\r
- * PGTStorageFile::PGTStorageFile(), read by getFormat().\r
- *\r
- * @private\r
- */\r
- var $_format;\r
-\r
- /**\r
- * This method returns the format to use when storing PGT's on the filesystem.\r
- *\r
- * @return a string corresponding to the format used (plain or xml).\r
- *\r
- * @private\r
- */\r
- function getFormat()\r
- {\r
- return $this->_format;\r
- }\r
-\r
- // ########################################################################\r
- // DEBUGGING\r
- // ########################################################################\r
- \r
- /**\r
- * This method returns an informational string giving the type of storage\r
- * used by the object (used for debugging purposes).\r
- *\r
- * @return an informational string.\r
- * @public\r
- */\r
- function getStorageType()\r
- {\r
- return "file";\r
- }\r
-\r
- /**\r
- * This method returns an informational string giving informations on the\r
- * parameters of the storage.(used for debugging purposes).\r
- *\r
- * @return an informational string.\r
- * @public\r
- */\r
- function getStorageInfo()\r
- {\r
- return 'path=`'.$this->getPath().'\', format=`'.$this->getFormat().'\'';\r
- }\r
-\r
- // ########################################################################\r
- // CONSTRUCTOR\r
- // ########################################################################\r
- \r
- /**\r
- * The class constructor, called by CASClient::SetPGTStorageFile().\r
- *\r
- * @param $cas_parent the CASClient instance that creates the object.\r
- * @param $format the format used to store the PGT's (`plain' and `xml' allowed).\r
- * @param $path the path where the PGT's should be stored\r
- *\r
- * @public\r
- */\r
- function PGTStorageFile($cas_parent,$format,$path)\r
- {\r
- phpCAS::traceBegin();\r
- // call the ancestor's constructor\r
- $this->PGTStorage($cas_parent);\r
-\r
- if (empty($format) ) $format = CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT;\r
- if (empty($path) ) $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH;\r
-\r
- // check that the path is an absolute path\r
- if (getenv("OS")=="Windows_NT"){\r
- \r
- if (!preg_match('`^[a-zA-Z]:`', $path)) {\r
- phpCAS::error('an absolute path is needed for PGT storage to file');\r
- }\r
- \r
- }\r
- else\r
- {\r
- \r
- if ( $path[0] != '/' ) {\r
- phpCAS::error('an absolute path is needed for PGT storage to file');\r
- }\r
-\r
- // store the path (with a leading and trailing '/') \r
- $path = preg_replace('|[/]*$|','/',$path);\r
- $path = preg_replace('|^[/]*|','/',$path);\r
- }\r
- \r
- $this->_path = $path;\r
- // check the format and store it\r
- switch ($format) {\r
- case CAS_PGT_STORAGE_FILE_FORMAT_PLAIN:\r
- case CAS_PGT_STORAGE_FILE_FORMAT_XML:\r
- $this->_format = $format;\r
- break;\r
- default:\r
- phpCAS::error('unknown PGT file storage format (`'.CAS_PGT_STORAGE_FILE_FORMAT_PLAIN.'\' and `'.CAS_PGT_STORAGE_FILE_FORMAT_XML.'\' allowed)');\r
- }\r
- phpCAS::traceEnd(); \r
- }\r
-\r
- // ########################################################################\r
- // INITIALIZATION\r
- // ########################################################################\r
- \r
- /**\r
- * This method is used to initialize the storage. Halts on error.\r
- *\r
- * @public\r
- */\r
- function init()\r
- {\r
- phpCAS::traceBegin();\r
- // if the storage has already been initialized, return immediatly\r
- if ( $this->isInitialized() )\r
- return;\r
- // call the ancestor's method (mark as initialized)\r
- parent::init();\r
- phpCAS::traceEnd(); \r
- }\r
-\r
- // ########################################################################\r
- // PGT I/O\r
- // ########################################################################\r
-\r
- /**\r
- * This method returns the filename corresponding to a PGT Iou.\r
- *\r
- * @param $pgt_iou the PGT iou.\r
- *\r
- * @return a filename\r
- * @private\r
- */\r
- function getPGTIouFilename($pgt_iou)\r
- {\r
- phpCAS::traceBegin();\r
- $filename = $this->getPath().$pgt_iou.'.'.$this->getFormat();\r
- phpCAS::traceEnd($filename);\r
- return $filename;\r
- }\r
- \r
- /**\r
- * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a\r
- * warning on error.\r
- *\r
- * @param $pgt the PGT\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @public\r
- */\r
- function write($pgt,$pgt_iou)\r
- {\r
- phpCAS::traceBegin();\r
- $fname = $this->getPGTIouFilename($pgt_iou);\r
- if ( $f=fopen($fname,"w") ) {\r
- if ( fputs($f,$pgt) === FALSE ) {\r
- phpCAS::error('could not write PGT to `'.$fname.'\'');\r
- }\r
- fclose($f);\r
- } else {\r
- phpCAS::error('could not open `'.$fname.'\'');\r
- }\r
- phpCAS::traceEnd(); \r
- }\r
-\r
- /**\r
- * This method reads a PGT corresponding to a PGT Iou and deletes the \r
- * corresponding file.\r
- *\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @return the corresponding PGT, or FALSE on error\r
- *\r
- * @public\r
- */\r
- function read($pgt_iou)\r
- {\r
- phpCAS::traceBegin();\r
- $pgt = FALSE;\r
- $fname = $this->getPGTIouFilename($pgt_iou);\r
- if ( !($f=fopen($fname,"r")) ) {\r
- phpCAS::trace('could not open `'.$fname.'\'');\r
- } else {\r
- if ( ($pgt=fgets($f)) === FALSE ) {\r
- phpCAS::trace('could not read PGT from `'.$fname.'\'');\r
- } \r
- fclose($f);\r
- }\r
-\r
- // delete the PGT file\r
- @unlink($fname);\r
-\r
- phpCAS::traceEnd($pgt);\r
- return $pgt;\r
- }\r
- \r
- /** @} */\r
- \r
-}\r
-\r
- \r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-/*\r
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.\r
- * All rights reserved.\r
- * \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * \r
- * * Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the following disclaimer.\r
- * * Redistributions in binary form must reproduce the above copyright notice,\r
- * this list of conditions and the following disclaimer in the documentation\r
- * and/or other materials provided with the distribution.\r
- * * Neither the name of the ESUP-Portail consortium & the JA-SIG\r
- * Collaborative nor the names of its contributors may be used to endorse or\r
- * promote products derived from this software without specific prior\r
- * written permission.\r
-\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-/**\r
- * @file CAS/PGTStorage/pgt-main.php\r
- * Basic class for PGT storage\r
- */\r
-\r
-/**\r
- * @class PGTStorage\r
- * The PGTStorage class is a generic class for PGT storage. This class should\r
- * not be instanciated itself but inherited by specific PGT storage classes.\r
- *\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * @ingroup internalPGTStorage\r
- */\r
-\r
-class PGTStorage\r
-{\r
- /** \r
- * @addtogroup internalPGTStorage\r
- * @{ \r
- */\r
-\r
- // ########################################################################\r
- // CONSTRUCTOR\r
- // ########################################################################\r
- \r
- /**\r
- * The constructor of the class, should be called only by inherited classes.\r
- *\r
- * @param $cas_parent the CASclient instance that creates the current object.\r
- *\r
- * @protected\r
- */\r
- function PGTStorage($cas_parent)\r
- {\r
- phpCAS::traceBegin();\r
- if ( !$cas_parent->isProxy() ) {\r
- phpCAS::error('defining PGT storage makes no sense when not using a CAS proxy'); \r
- }\r
- phpCAS::traceEnd();\r
- }\r
-\r
- // ########################################################################\r
- // DEBUGGING\r
- // ########################################################################\r
- \r
- /**\r
- * This virtual method returns an informational string giving the type of storage\r
- * used by the object (used for debugging purposes).\r
- *\r
- * @public\r
- */\r
- function getStorageType()\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- /**\r
- * This virtual method returns an informational string giving informations on the\r
- * parameters of the storage.(used for debugging purposes).\r
- *\r
- * @public\r
- */\r
- function getStorageInfo()\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- // ########################################################################\r
- // ERROR HANDLING\r
- // ########################################################################\r
- \r
- /**\r
- * string used to store an error message. Written by PGTStorage::setErrorMessage(),\r
- * read by PGTStorage::getErrorMessage().\r
- *\r
- * @hideinitializer\r
- * @private\r
- * @deprecated not used.\r
- */\r
- var $_error_message=FALSE;\r
-\r
- /**\r
- * This method sets en error message, which can be read later by \r
- * PGTStorage::getErrorMessage().\r
- *\r
- * @param $error_message an error message\r
- *\r
- * @protected\r
- * @deprecated not used.\r
- */\r
- function setErrorMessage($error_message)\r
- {\r
- $this->_error_message = $error_message;\r
- }\r
-\r
- /**\r
- * This method returns an error message set by PGTStorage::setErrorMessage().\r
- *\r
- * @return an error message when set by PGTStorage::setErrorMessage(), FALSE\r
- * otherwise.\r
- *\r
- * @public\r
- * @deprecated not used.\r
- */\r
- function getErrorMessage()\r
- {\r
- return $this->_error_message;\r
- }\r
-\r
- // ########################################################################\r
- // INITIALIZATION\r
- // ########################################################################\r
-\r
- /**\r
- * a boolean telling if the storage has already been initialized. Written by \r
- * PGTStorage::init(), read by PGTStorage::isInitialized().\r
- *\r
- * @hideinitializer\r
- * @private\r
- */\r
- var $_initialized = FALSE;\r
-\r
- /**\r
- * This method tells if the storage has already been intialized.\r
- *\r
- * @return a boolean\r
- *\r
- * @protected\r
- */\r
- function isInitialized()\r
- {\r
- return $this->_initialized;\r
- }\r
-\r
- /**\r
- * This virtual method initializes the object.\r
- *\r
- * @protected\r
- */\r
- function init()\r
- {\r
- $this->_initialized = TRUE;\r
- }\r
-\r
- // ########################################################################\r
- // PGT I/O\r
- // ########################################################################\r
-\r
- /**\r
- * This virtual method stores a PGT and its corresponding PGT Iuo.\r
- * @note Should never be called.\r
- *\r
- * @param $pgt the PGT\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @protected\r
- */\r
- function write($pgt,$pgt_iou)\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- /**\r
- * This virtual method reads a PGT corresponding to a PGT Iou and deletes\r
- * the corresponding storage entry.\r
- * @note Should never be called.\r
- *\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @protected\r
- */\r
- function read($pgt_iou)\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- /** @} */\r
- \r
-} \r
-\r
-// include specific PGT storage classes\r
-include_once(dirname(__FILE__).'/pgt-file.php'); \r
-include_once(dirname(__FILE__).'/pgt-db.php');\r
- \r
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-
-/*
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.
- * 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.
- * * Neither the name of the ESUP-Portail consortium & the JA-SIG
- * Collaborative nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
-
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
- */
-
-/**
- * @file CAS/client.php
- * Main class of the phpCAS library
- */
-
-// include internationalization stuff
-include_once(dirname(__FILE__).'/languages/languages.php');
-
-// include PGT storage classes
-include_once(dirname(__FILE__).'/PGTStorage/pgt-main.php');
-
-/**
- * @class CASClient
- * The CASClient class is a client interface that provides CAS authentication
- * to PHP applications.
- *
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>
- */
-
-class CASClient
-{
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX CONFIGURATION XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // HTML OUTPUT
- // ########################################################################
- /**
- * @addtogroup internalOutput
- * @{
- */
-
- /**
- * This method filters a string by replacing special tokens by appropriate values
- * and prints it. The corresponding tokens are taken into account:
- * - __CAS_VERSION__
- * - __PHPCAS_VERSION__
- * - __SERVER_BASE_URL__
- *
- * Used by CASClient::PrintHTMLHeader() and CASClient::printHTMLFooter().
- *
- * @param $str the string to filter and output
- *
- * @private
- */
- function HTMLFilterOutput($str)
- {
- $str = str_replace('__CAS_VERSION__',$this->getServerVersion(),$str);
- $str = str_replace('__PHPCAS_VERSION__',phpCAS::getVersion(),$str);
- $str = str_replace('__SERVER_BASE_URL__',$this->getServerBaseURL(),$str);
- echo $str;
- }
-
- /**
- * A string used to print the header of HTML pages. Written by CASClient::setHTMLHeader(),
- * read by CASClient::printHTMLHeader().
- *
- * @hideinitializer
- * @private
- * @see CASClient::setHTMLHeader, CASClient::printHTMLHeader()
- */
- var $_output_header = '';
-
- /**
- * This method prints the header of the HTML output (after filtering). If
- * CASClient::setHTMLHeader() was not used, a default header is output.
- *
- * @param $title the title of the page
- *
- * @see HTMLFilterOutput()
- * @private
- */
- function printHTMLHeader($title)
- {
- $this->HTMLFilterOutput(str_replace('__TITLE__',
- $title,
- (empty($this->_output_header)
- ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
- : $this->_output_header)
- )
- );
- }
-
- /**
- * A string used to print the footer of HTML pages. Written by CASClient::setHTMLFooter(),
- * read by printHTMLFooter().
- *
- * @hideinitializer
- * @private
- * @see CASClient::setHTMLFooter, CASClient::printHTMLFooter()
- */
- var $_output_footer = '';
-
- /**
- * This method prints the footer of the HTML output (after filtering). If
- * CASClient::setHTMLFooter() was not used, a default footer is output.
- *
- * @see HTMLFilterOutput()
- * @private
- */
- function printHTMLFooter()
- {
- $this->HTMLFilterOutput(empty($this->_output_footer)
- ?('<hr><address>phpCAS __PHPCAS_VERSION__ '.$this->getString(CAS_STR_USING_SERVER).' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
- :$this->_output_footer);
- }
-
- /**
- * This method set the HTML header used for all outputs.
- *
- * @param $header the HTML header.
- *
- * @public
- */
- function setHTMLHeader($header)
- {
- $this->_output_header = $header;
- }
-
- /**
- * This method set the HTML footer used for all outputs.
- *
- * @param $footer the HTML footer.
- *
- * @public
- */
- function setHTMLFooter($footer)
- {
- $this->_output_footer = $footer;
- }
-
- /** @} */
- // ########################################################################
- // INTERNATIONALIZATION
- // ########################################################################
- /**
- * @addtogroup internalLang
- * @{
- */
- /**
- * A string corresponding to the language used by phpCAS. Written by
- * CASClient::setLang(), read by CASClient::getLang().
-
- * @note debugging information is always in english (debug purposes only).
- *
- * @hideinitializer
- * @private
- * @sa CASClient::_strings, CASClient::getString()
- */
- var $_lang = '';
-
- /**
- * This method returns the language used by phpCAS.
- *
- * @return a string representing the language
- *
- * @private
- */
- function getLang()
- {
- if ( empty($this->_lang) )
- $this->setLang(PHPCAS_LANG_DEFAULT);
- return $this->_lang;
- }
-
- /**
- * array containing the strings used by phpCAS. Written by CASClient::setLang(), read by
- * CASClient::getString() and used by CASClient::setLang().
- *
- * @note This array is filled by instructions in CAS/languages/<$this->_lang>.php
- *
- * @private
- * @see CASClient::_lang, CASClient::getString(), CASClient::setLang(), CASClient::getLang()
- */
- var $_strings;
-
- /**
- * This method returns a string depending on the language.
- *
- * @param $str the index of the string in $_string.
- *
- * @return the string corresponding to $index in $string.
- *
- * @private
- */
- function getString($str)
- {
- // call CASclient::getLang() to be sure the language is initialized
- $this->getLang();
-
- if ( !isset($this->_strings[$str]) ) {
- trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR);
- }
- return $this->_strings[$str];
- }
-
- /**
- * This method is used to set the language used by phpCAS.
- * @note Can be called only once.
- *
- * @param $lang a string representing the language.
- *
- * @public
- * @sa CAS_LANG_FRENCH, CAS_LANG_ENGLISH
- */
- function setLang($lang)
- {
- // include the corresponding language file
- include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
-
- if ( !is_array($this->_strings) ) {
- trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR);
- }
- $this->_lang = $lang;
- }
-
- /** @} */
- // ########################################################################
- // CAS SERVER CONFIG
- // ########################################################################
- /**
- * @addtogroup internalConfig
- * @{
- */
-
- /**
- * a record to store information about the CAS server.
- * - $_server["version"]: the version of the CAS server
- * - $_server["hostname"]: the hostname of the CAS server
- * - $_server["port"]: the port the CAS server is running on
- * - $_server["uri"]: the base URI the CAS server is responding on
- * - $_server["base_url"]: the base URL of the CAS server
- * - $_server["login_url"]: the login URL of the CAS server
- * - $_server["service_validate_url"]: the service validating URL of the CAS server
- * - $_server["proxy_url"]: the proxy URL of the CAS server
- * - $_server["proxy_validate_url"]: the proxy validating URL of the CAS server
- * - $_server["logout_url"]: the logout URL of the CAS server
- *
- * $_server["version"], $_server["hostname"], $_server["port"] and $_server["uri"]
- * are written by CASClient::CASClient(), read by CASClient::getServerVersion(),
- * CASClient::getServerHostname(), CASClient::getServerPort() and CASClient::getServerURI().
- *
- * The other fields are written and read by CASClient::getServerBaseURL(),
- * CASClient::getServerLoginURL(), CASClient::getServerServiceValidateURL(),
- * CASClient::getServerProxyValidateURL() and CASClient::getServerLogoutURL().
- *
- * @hideinitializer
- * @private
- */
- var $_server = array(
- 'version' => -1,
- 'hostname' => 'none',
- 'port' => -1,
- 'uri' => 'none'
- );
-
- /**
- * This method is used to retrieve the version of the CAS server.
- * @return the version of the CAS server.
- * @private
- */
- function getServerVersion()
- {
- return $this->_server['version'];
- }
-
- /**
- * This method is used to retrieve the hostname of the CAS server.
- * @return the hostname of the CAS server.
- * @private
- */
- function getServerHostname()
- { return $this->_server['hostname']; }
-
- /**
- * This method is used to retrieve the port of the CAS server.
- * @return the port of the CAS server.
- * @private
- */
- function getServerPort()
- { return $this->_server['port']; }
-
- /**
- * This method is used to retrieve the URI of the CAS server.
- * @return a URI.
- * @private
- */
- function getServerURI()
- { return $this->_server['uri']; }
-
- /**
- * This method is used to retrieve the base URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerBaseURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['base_url']) ) {
- $this->_server['base_url'] = 'https://'
- .$this->getServerHostname()
- .':'
- .$this->getServerPort()
- .$this->getServerURI();
- }
- return $this->_server['base_url'];
- }
-
- /**
- * This method is used to retrieve the login URL of the CAS server.
- * @param $gateway true to check authentication, false to force it
- * @param $renew true to force the authentication with the CAS server
- * NOTE : It is recommended that CAS implementations ignore the
- "gateway" parameter if "renew" is set
- * @return a URL.
- * @private
- */
- function getServerLoginURL($gateway=false,$renew=false) {
- phpCAS::traceBegin();
- // the URL is build only when needed
- if ( empty($this->_server['login_url']) ) {
- $this->_server['login_url'] = $this->getServerBaseURL();
- $this->_server['login_url'] .= 'login?service=';
- // $this->_server['login_url'] .= preg_replace('/&/','%26',$this->getURL());
- $this->_server['login_url'] .= urlencode($this->getURL());
- if($renew) {
- // It is recommended that when the "renew" parameter is set, its value be "true"
- $this->_server['login_url'] .= '&renew=true';
- } elseif ($gateway) {
- // It is recommended that when the "gateway" parameter is set, its value be "true"
- $this->_server['login_url'] .= '&gateway=true';
- }
- }
- phpCAS::traceEnd($this->_server['login_url']);
- return $this->_server['login_url'];
- }
-
- /**
- * This method sets the login URL of the CAS server.
- * @param $url the login URL
- * @private
- * @since 0.4.21 by Wyman Chan
- */
- function setServerLoginURL($url)
- {
- return $this->_server['login_url'] = $url;
- }
-
-
- /**
- * This method sets the serviceValidate URL of the CAS server.
- * @param $url the serviceValidate URL
- * @private
- * @since 1.1.0 by Joachim Fritschi
- */
- function setServerServiceValidateURL($url)
- {
- return $this->_server['service_validate_url'] = $url;
- }
-
-
- /**
- * This method sets the proxyValidate URL of the CAS server.
- * @param $url the proxyValidate URL
- * @private
- * @since 1.1.0 by Joachim Fritschi
- */
- function setServerProxyValidateURL($url)
- {
- return $this->_server['proxy_validate_url'] = $url;
- }
-
-
- /**
- * This method sets the samlValidate URL of the CAS server.
- * @param $url the samlValidate URL
- * @private
- * @since 1.1.0 by Joachim Fritschi
- */
- function setServerSamlValidateURL($url)
- {
- return $this->_server['saml_validate_url'] = $url;
- }
-
-
- /**
- * This method is used to retrieve the service validating URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerServiceValidateURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['service_validate_url']) ) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- $this->_server['service_validate_url'] = $this->getServerBaseURL().'validate';
- break;
- case CAS_VERSION_2_0:
- $this->_server['service_validate_url'] = $this->getServerBaseURL().'serviceValidate';
- break;
- }
- }
- // return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
- return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL());
- }
- /**
- * This method is used to retrieve the SAML validating URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerSamlValidateURL()
- {
- phpCAS::traceBegin();
- // the URL is build only when needed
- if ( empty($this->_server['saml_validate_url']) ) {
- switch ($this->getServerVersion()) {
- case SAML_VERSION_1_1:
- $this->_server['saml_validate_url'] = $this->getServerBaseURL().'samlValidate';
- break;
- }
- }
- phpCAS::traceEnd($this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL()));
- return $this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL());
- }
- /**
- * This method is used to retrieve the proxy validating URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerProxyValidateURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['proxy_validate_url']) ) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- $this->_server['proxy_validate_url'] = '';
- break;
- case CAS_VERSION_2_0:
- $this->_server['proxy_validate_url'] = $this->getServerBaseURL().'proxyValidate';
- break;
- }
- }
- // return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
- return $this->_server['proxy_validate_url'].'?service='.urlencode($this->getURL());
- }
-
- /**
- * This method is used to retrieve the proxy URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerProxyURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['proxy_url']) ) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- $this->_server['proxy_url'] = '';
- break;
- case CAS_VERSION_2_0:
- $this->_server['proxy_url'] = $this->getServerBaseURL().'proxy';
- break;
- }
- }
- return $this->_server['proxy_url'];
- }
-
- /**
- * This method is used to retrieve the logout URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerLogoutURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['logout_url']) ) {
- $this->_server['logout_url'] = $this->getServerBaseURL().'logout';
- }
- return $this->_server['logout_url'];
- }
-
- /**
- * This method sets the logout URL of the CAS server.
- * @param $url the logout URL
- * @private
- * @since 0.4.21 by Wyman Chan
- */
- function setServerLogoutURL($url)
- {
- return $this->_server['logout_url'] = $url;
- }
-
- /**
- * An array to store extra curl options.
- */
- var $_curl_options = array();
-
- /**
- * This method is used to set additional user curl options.
- */
- function setExtraCurlOption($key, $value)
- {
- $this->_curl_options[$key] = $value;
- }
-
- /**
- * This method checks to see if the request is secured via HTTPS
- * @return true if https, false otherwise
- * @private
- */
- function isHttps() {
- //if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ) {
- //0.4.24 by Hinnack
- if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
- return true;
- } else {
- return false;
- }
- }
-
- // ########################################################################
- // CONSTRUCTOR
- // ########################################################################
- /**
- * CASClient constructor.
- *
- * @param $server_version the version of the CAS server
- * @param $proxy TRUE if the CAS client is a CAS proxy, FALSE otherwise
- * @param $server_hostname the hostname of the CAS server
- * @param $server_port the port the CAS server is running on
- * @param $server_uri the URI the CAS server is responding on
- * @param $start_session Have phpCAS start PHP sessions (default true)
- *
- * @return a newly created CASClient object
- *
- * @public
- */
- function CASClient(
- $server_version,
- $proxy,
- $server_hostname,
- $server_port,
- $server_uri,
- $start_session = true) {
-
- phpCAS::traceBegin();
-
- // the redirect header() call and DOM parsing code from domxml-php4-php5.php won't work in PHP4 compatibility mode
- if (version_compare(PHP_VERSION,'5','>=') && ini_get('zend.ze1_compatibility_mode')) {
- phpCAS::error('phpCAS cannot support zend.ze1_compatibility_mode. Sorry.');
- }
- $this->_start_session = $start_session;
-
- if ($this->_start_session && session_id())
- {
- phpCAS :: error("Another session was started before phpcas. Either disable the session" .
- " handling for phpcas in the client() call or modify your application to leave" .
- " session handling to phpcas");
- }
- // skip Session Handling for logout requests and if don't want it'
- if ($start_session && !$this->isLogoutRequest())
- {
- phpCAS :: trace("Starting a new session");
- session_start();
- }
-
-
- // are we in proxy mode ?
- $this->_proxy = $proxy;
-
- //check version
- switch ($server_version) {
- case CAS_VERSION_1_0:
- if ( $this->isProxy() )
- phpCAS::error('CAS proxies are not supported in CAS '
- .$server_version);
- break;
- case CAS_VERSION_2_0:
- break;
- case SAML_VERSION_1_1:
- break;
- default:
- phpCAS::error('this version of CAS (`'
- .$server_version
- .'\') is not supported by phpCAS '
- .phpCAS::getVersion());
- }
- $this->_server['version'] = $server_version;
-
- // check hostname
- if ( empty($server_hostname)
- || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
- phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
- }
- $this->_server['hostname'] = $server_hostname;
-
- // check port
- if ( $server_port == 0
- || !is_int($server_port) ) {
- phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
- }
- $this->_server['port'] = $server_port;
-
- // check URI
- if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
- phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
- }
- // add leading and trailing `/' and remove doubles
- $server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/');
- $this->_server['uri'] = $server_uri;
-
- // set to callback mode if PgtIou and PgtId CGI GET parameters are provided
- if ( $this->isProxy() ) {
- $this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
- }
-
- if ( $this->isCallbackMode() ) {
- //callback mode: check that phpCAS is secured
- if ( !$this->isHttps() ) {
- phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
- }
- } else {
- //normal mode: get ticket and remove it from CGI parameters for developpers
- $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0: // check for a Service Ticket
- if( preg_match('/^ST-/',$ticket) ) {
- phpCAS::trace('ST \''.$ticket.'\' found');
- //ST present
- $this->setST($ticket);
- //ticket has been taken into account, unset it to hide it to applications
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
- }
- break;
- case CAS_VERSION_2_0: // check for a Service or Proxy Ticket
- if( preg_match('/^[SP]T-/',$ticket) ) {
- phpCAS::trace('ST or PT \''.$ticket.'\' found');
- $this->setPT($ticket);
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
- }
- break;
- case SAML_VERSION_1_1: // SAML just does Service Tickets
- if( preg_match('/^[SP]T-/',$ticket) ) {
- phpCAS::trace('SA \''.$ticket.'\' found');
- $this->setSA($ticket);
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
- }
- break;
- }
- }
- phpCAS::traceEnd();
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX Session Handling XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- /**
- * A variable to whether phpcas will use its own session handling. Default = true
- * @hideinitializer
- * @private
- */
- var $_start_session = true;
-
- function setStartSession($session)
- {
- $this->_start_session = session;
- }
-
- function getStartSession($session)
- {
- $this->_start_session = session;
- }
-
- /**
- * Renaming the session
- */
- function renameSession($ticket)
- {
- phpCAS::traceBegin();
- if($this->_start_session){
- if (!empty ($this->_user))
- {
- $old_session = $_SESSION;
- session_destroy();
- // set up a new session, of name based on the ticket
- $session_id = preg_replace('/[^\w]/', '', $ticket);
- phpCAS :: trace("Session ID: ".$session_id);
- session_id($session_id);
- session_start();
- phpCAS :: trace("Restoring old session vars");
- $_SESSION = $old_session;
- } else
- {
- phpCAS :: error('Session should only be renamed after successfull authentication');
- }
- }else{
- phpCAS :: trace("Skipping session rename since phpCAS is not handling the session.");
- }
- phpCAS::traceEnd();
- }
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX AUTHENTICATION XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- /**
- * @addtogroup internalAuthentication
- * @{
- */
-
- /**
- * The Authenticated user. Written by CASClient::setUser(), read by CASClient::getUser().
- * @attention client applications should use phpCAS::getUser().
- *
- * @hideinitializer
- * @private
- */
- var $_user = '';
-
- /**
- * This method sets the CAS user's login name.
- *
- * @param $user the login name of the authenticated user.
- *
- * @private
- */
- function setUser($user)
- {
- $this->_user = $user;
- }
-
- /**
- * This method returns the CAS user's login name.
- * @warning should be called only after CASClient::forceAuthentication() or
- * CASClient::isAuthenticated(), otherwise halt with an error.
- *
- * @return the login name of the authenticated user
- */
- function getUser()
- {
- if ( empty($this->_user) ) {
- phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
- }
- return $this->_user;
- }
-
-
-
- /***********************************************************************************************************************
- * Atrributes section
- *
- * @author Matthias Crauwels <matthias.crauwels@ugent.be>, Ghent University, Belgium
- *
- ***********************************************************************************************************************/
- /**
- * The Authenticated users attributes. Written by CASClient::setAttributes(), read by CASClient::getAttributes().
- * @attention client applications should use phpCAS::getAttributes().
- *
- * @hideinitializer
- * @private
- */
- var $_attributes = array();
-
- function setAttributes($attributes)
- { $this->_attributes = $attributes; }
-
- function getAttributes() {
- if ( empty($this->_user) ) { // if no user is set, there shouldn't be any attributes also...
- phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
- }
- return $this->_attributes;
- }
-
- function hasAttributes()
- { return !empty($this->_attributes); }
-
- function hasAttribute($key)
- { return (is_array($this->_attributes) && array_key_exists($key, $this->_attributes)); }
-
- function getAttribute($key) {
- if($this->hasAttribute($key)) {
- return $this->_attributes[$key];
- }
- }
-
- /**
- * This method is called to renew the authentication of the user
- * If the user is authenticated, renew the connection
- * If not, redirect to CAS
- * @public
- */
- function renewAuthentication(){
- phpCAS::traceBegin();
- // Either way, the user is authenticated by CAS
- if( isset( $_SESSION['phpCAS']['auth_checked'] ) )
- unset($_SESSION['phpCAS']['auth_checked']);
- if ( $this->isAuthenticated() ) {
- phpCAS::trace('user already authenticated; renew');
- $this->redirectToCas(false,true);
- } else {
- $this->redirectToCas();
- }
- phpCAS::traceEnd();
- }
-
- /**
- * This method is called to be sure that the user is authenticated. When not
- * authenticated, halt by redirecting to the CAS server; otherwise return TRUE.
- * @return TRUE when the user is authenticated; otherwise halt.
- * @public
- */
- function forceAuthentication()
- {
- phpCAS::traceBegin();
-
- if ( $this->isAuthenticated() ) {
- // the user is authenticated, nothing to be done.
- phpCAS::trace('no need to authenticate');
- $res = TRUE;
- } else {
- // the user is not authenticated, redirect to the CAS server
- if (isset($_SESSION['phpCAS']['auth_checked'])) {
- unset($_SESSION['phpCAS']['auth_checked']);
- }
- $this->redirectToCas(FALSE/* no gateway */);
- // never reached
- $res = FALSE;
- }
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * An integer that gives the number of times authentication will be cached before rechecked.
- *
- * @hideinitializer
- * @private
- */
- var $_cache_times_for_auth_recheck = 0;
-
- /**
- * Set the number of times authentication will be cached before rechecked.
- *
- * @param $n an integer.
- *
- * @public
- */
- function setCacheTimesForAuthRecheck($n)
- {
- $this->_cache_times_for_auth_recheck = $n;
- }
-
- /**
- * This method is called to check whether the user is authenticated or not.
- * @return TRUE when the user is authenticated, FALSE otherwise.
- * @public
- */
- function checkAuthentication()
- {
- phpCAS::traceBegin();
-
- if ( $this->isAuthenticated() ) {
- phpCAS::trace('user is authenticated');
- $res = TRUE;
- } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
- // the previous request has redirected the client to the CAS server with gateway=true
- unset($_SESSION['phpCAS']['auth_checked']);
- $res = FALSE;
- } else {
- // $_SESSION['phpCAS']['auth_checked'] = true;
- // $this->redirectToCas(TRUE/* gateway */);
- // // never reached
- // $res = FALSE;
- // avoid a check against CAS on every request
- if (! isset($_SESSION['phpCAS']['unauth_count']) )
- $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
-
- if (($_SESSION['phpCAS']['unauth_count'] != -2 && $this->_cache_times_for_auth_recheck == -1)
- || ($_SESSION['phpCAS']['unauth_count'] >= 0 && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck))
- {
- $res = FALSE;
-
- if ($this->_cache_times_for_auth_recheck != -1)
- {
- $_SESSION['phpCAS']['unauth_count']++;
- phpCAS::trace('user is not authenticated (cached for '.$_SESSION['phpCAS']['unauth_count'].' times of '.$this->_cache_times_for_auth_recheck.')');
- }
- else
- {
- phpCAS::trace('user is not authenticated (cached for until login pressed)');
- }
- }
- else
- {
- $_SESSION['phpCAS']['unauth_count'] = 0;
- $_SESSION['phpCAS']['auth_checked'] = true;
- phpCAS::trace('user is not authenticated (cache reset)');
- $this->redirectToCas(TRUE/* gateway */);
- // never reached
- $res = FALSE;
- }
- }
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method is called to check if the user is authenticated (previously or by
- * tickets given in the URL).
- *
- * @return TRUE when the user is authenticated. Also may redirect to the same URL without the ticket.
- *
- * @public
- */
- function isAuthenticated()
- {
- phpCAS::traceBegin();
- $res = FALSE;
- $validate_url = '';
-
- if ( $this->wasPreviouslyAuthenticated() ) {
- if($this->hasST() || $this->hasPT() || $this->hasSA()){
- // User has a additional ticket but was already authenticated
- phpCAS::trace('ticket was present and will be discarded, use renewAuthenticate()');
- header('Location: '.$this->getURL());
- phpCAS::log( "Prepare redirect to remove ticket: ".$this->getURL() );
- }else{
- // the user has already (previously during the session) been
- // authenticated, nothing to be done.
- phpCAS::trace('user was already authenticated, no need to look for tickets');
- }
- $res = TRUE;
- }
- else {
- if ( $this->hasST() ) {
- // if a Service Ticket was given, validate it
- phpCAS::trace('ST `'.$this->getST().'\' is present');
- $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
- phpCAS::trace('ST `'.$this->getST().'\' was validated');
- if ( $this->isProxy() ) {
- $this->validatePGT($validate_url,$text_response,$tree_response); // idem
- phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
- $_SESSION['phpCAS']['pgt'] = $this->getPGT();
- }
- $_SESSION['phpCAS']['user'] = $this->getUser();
- $res = TRUE;
- }
- elseif ( $this->hasPT() ) {
- // if a Proxy Ticket was given, validate it
- phpCAS::trace('PT `'.$this->getPT().'\' is present');
- $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
- phpCAS::trace('PT `'.$this->getPT().'\' was validated');
- if ( $this->isProxy() ) {
- $this->validatePGT($validate_url,$text_response,$tree_response); // idem
- phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
- $_SESSION['phpCAS']['pgt'] = $this->getPGT();
- }
- $_SESSION['phpCAS']['user'] = $this->getUser();
- $res = TRUE;
- }
- elseif ( $this->hasSA() ) {
- // if we have a SAML ticket, validate it.
- phpCAS::trace('SA `'.$this->getSA().'\' is present');
- $this->validateSA($validate_url,$text_response,$tree_response); // if it fails, it halts
- phpCAS::trace('SA `'.$this->getSA().'\' was validated');
- $_SESSION['phpCAS']['user'] = $this->getUser();
- $_SESSION['phpCAS']['attributes'] = $this->getAttributes();
- $res = TRUE;
- }
- else {
- // no ticket given, not authenticated
- phpCAS::trace('no ticket found');
- }
- if ($res) {
- // if called with a ticket parameter, we need to redirect to the app without the ticket so that CAS-ification is transparent to the browser (for later POSTS)
- // most of the checks and errors should have been made now, so we're safe for redirect without masking error messages.
- header('Location: '.$this->getURL());
- phpCAS::log( "Prepare redirect to : ".$this->getURL() );
- }
- }
-
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method tells if the current session is authenticated.
- * @return true if authenticated based soley on $_SESSION variable
- * @since 0.4.22 by Brendan Arnold
- */
- function isSessionAuthenticated ()
- {
- return !empty($_SESSION['phpCAS']['user']);
- }
-
- /**
- * This method tells if the user has already been (previously) authenticated
- * by looking into the session variables.
- *
- * @note This function switches to callback mode when needed.
- *
- * @return TRUE when the user has already been authenticated; FALSE otherwise.
- *
- * @private
- */
- function wasPreviouslyAuthenticated()
- {
- phpCAS::traceBegin();
-
- if ( $this->isCallbackMode() ) {
- $this->callback();
- }
-
- $auth = FALSE;
-
- if ( $this->isProxy() ) {
- // CAS proxy: username and PGT must be present
- if ( $this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
- // authentication already done
- $this->setUser($_SESSION['phpCAS']['user']);
- $this->setPGT($_SESSION['phpCAS']['pgt']);
- phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\'');
- $auth = TRUE;
- } elseif ( $this->isSessionAuthenticated() && empty($_SESSION['phpCAS']['pgt']) ) {
- // these two variables should be empty or not empty at the same time
- phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty');
- // unset all tickets to enforce authentication
- unset($_SESSION['phpCAS']);
- $this->setST('');
- $this->setPT('');
- } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
- // these two variables should be empty or not empty at the same time
- phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty');
- // unset all tickets to enforce authentication
- unset($_SESSION['phpCAS']);
- $this->setST('');
- $this->setPT('');
- } else {
- phpCAS::trace('neither user not PGT found');
- }
- } else {
- // `simple' CAS client (not a proxy): username must be present
- if ( $this->isSessionAuthenticated() ) {
- // authentication already done
- $this->setUser($_SESSION['phpCAS']['user']);
- if(isset($_SESSION['phpCAS']['attributes'])){
- $this->setAttributes($_SESSION['phpCAS']['attributes']);
- }
- phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\'');
- $auth = TRUE;
- } else {
- phpCAS::trace('no user found');
- }
- }
-
- phpCAS::traceEnd($auth);
- return $auth;
- }
-
- /**
- * This method is used to redirect the client to the CAS server.
- * It is used by CASClient::forceAuthentication() and CASClient::checkAuthentication().
- * @param $gateway true to check authentication, false to force it
- * @param $renew true to force the authentication with the CAS server
- * @public
- */
- function redirectToCas($gateway=false,$renew=false){
- phpCAS::traceBegin();
- $cas_url = $this->getServerLoginURL($gateway,$renew);
- header('Location: '.$cas_url);
- phpCAS::log( "Redirect to : ".$cas_url );
-
- $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED));
-
- printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
- $this->printHTMLFooter();
-
- phpCAS::traceExit();
- exit();
- }
-
-
- /**
- * This method is used to logout from CAS.
- * @params $params an array that contains the optional url and service parameters that will be passed to the CAS server
- * @public
- */
- function logout($params) {
- phpCAS::traceBegin();
- $cas_url = $this->getServerLogoutURL();
- $paramSeparator = '?';
- if (isset($params['url'])) {
- $cas_url = $cas_url . $paramSeparator . "url=" . urlencode($params['url']);
- $paramSeparator = '&';
- }
- if (isset($params['service'])) {
- $cas_url = $cas_url . $paramSeparator . "service=" . urlencode($params['service']);
- }
- header('Location: '.$cas_url);
- phpCAS::log( "Prepare redirect to : ".$cas_url );
-
- session_unset();
- session_destroy();
-
- $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
- printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
- $this->printHTMLFooter();
-
- phpCAS::traceExit();
- exit();
- }
-
- /**
- * @return true if the current request is a logout request.
- * @private
- */
- function isLogoutRequest() {
- return !empty($_POST['logoutRequest']);
- }
-
- /**
- * @return true if a logout request is allowed.
- * @private
- */
- function isLogoutRequestAllowed() {
- }
-
- /**
- * This method handles logout requests.
- * @param $check_client true to check the client bofore handling the request,
- * false not to perform any access control. True by default.
- * @param $allowed_clients an array of host names allowed to send logout requests.
- * By default, only the CAs server (declared in the constructor) will be allowed.
- * @public
- */
- function handleLogoutRequests($check_client=true, $allowed_clients=false) {
- phpCAS::traceBegin();
- if (!$this->isLogoutRequest()) {
- phpCAS::log("Not a logout request");
- phpCAS::traceEnd();
- return;
- }
- if(!$this->_start_session){
- phpCAS::log("phpCAS can't handle logout requests if it does not manage the session.");
- }
- phpCAS::log("Logout requested");
- phpCAS::log("SAML REQUEST: ".$_POST['logoutRequest']);
- if ($check_client) {
- if (!$allowed_clients) {
- $allowed_clients = array( $this->getServerHostname() );
- }
- $client_ip = $_SERVER['REMOTE_ADDR'];
- $client = gethostbyaddr($client_ip);
- phpCAS::log("Client: ".$client."/".$client_ip);
- $allowed = false;
- foreach ($allowed_clients as $allowed_client) {
- if (($client == $allowed_client) or ($client_ip == $allowed_client)) {
- phpCAS::log("Allowed client '".$allowed_client."' matches, logout request is allowed");
- $allowed = true;
- break;
- } else {
- phpCAS::log("Allowed client '".$allowed_client."' does not match");
- }
- }
- if (!$allowed) {
- phpCAS::error("Unauthorized logout request from client '".$client."'");
- printf("Unauthorized!");
- phpCAS::traceExit();
- exit();
- }
- } else {
- phpCAS::log("No access control set");
- }
- // Extract the ticket from the SAML Request
- preg_match("|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|", $_POST['logoutRequest'], $tick, PREG_OFFSET_CAPTURE, 3);
- $wrappedSamlSessionIndex = preg_replace('|<samlp:SessionIndex>|','',$tick[0][0]);
- $ticket2logout = preg_replace('|</samlp:SessionIndex>|','',$wrappedSamlSessionIndex);
- phpCAS::log("Ticket to logout: ".$ticket2logout);
- $session_id = preg_replace('/[^\w]/','',$ticket2logout);
- phpCAS::log("Session id: ".$session_id);
-
- // destroy a possible application session created before phpcas
- if(session_id()){
- session_unset();
- session_destroy();
- }
- // fix session ID
- session_id($session_id);
- $_COOKIE[session_name()]=$session_id;
- $_GET[session_name()]=$session_id;
-
- // Overwrite session
- session_start();
- session_unset();
- session_destroy();
- printf("Disconnected!");
- phpCAS::traceExit();
- exit();
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX BASIC CLIENT FEATURES (CAS 1.0) XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // ST
- // ########################################################################
- /**
- * @addtogroup internalBasic
- * @{
- */
-
- /**
- * the Service Ticket provided in the URL of the request if present
- * (empty otherwise). Written by CASClient::CASClient(), read by
- * CASClient::getST() and CASClient::hasPGT().
- *
- * @hideinitializer
- * @private
- */
- var $_st = '';
-
- /**
- * This method returns the Service Ticket provided in the URL of the request.
- * @return The service ticket.
- * @private
- */
- function getST()
- { return $this->_st; }
-
- /**
- * This method stores the Service Ticket.
- * @param $st The Service Ticket.
- * @private
- */
- function setST($st)
- { $this->_st = $st; }
-
- /**
- * This method tells if a Service Ticket was stored.
- * @return TRUE if a Service Ticket has been stored.
- * @private
- */
- function hasST()
- { return !empty($this->_st); }
-
- /** @} */
-
- // ########################################################################
- // ST VALIDATION
- // ########################################################################
- /**
- * @addtogroup internalBasic
- * @{
- */
-
- /**
- * the certificate of the CAS server.
- *
- * @hideinitializer
- * @private
- */
- var $_cas_server_cert = '';
-
- /**
- * the certificate of the CAS server CA.
- *
- * @hideinitializer
- * @private
- */
- var $_cas_server_ca_cert = '';
-
- /**
- * Set to true not to validate the CAS server.
- *
- * @hideinitializer
- * @private
- */
- var $_no_cas_server_validation = false;
-
- /**
- * Set the certificate of the CAS server.
- *
- * @param $cert the PEM certificate
- */
- function setCasServerCert($cert)
- {
- $this->_cas_server_cert = $cert;
- }
-
- /**
- * Set the CA certificate of the CAS server.
- *
- * @param $cert the PEM certificate of the CA that emited the cert of the server
- */
- function setCasServerCACert($cert)
- {
- $this->_cas_server_ca_cert = $cert;
- }
-
- /**
- * Set no SSL validation for the CAS server.
- */
- function setNoCasServerValidation()
- {
- $this->_no_cas_server_validation = true;
- }
-
- /**
- * This method is used to validate a ST; halt on failure, and sets $validate_url,
- * $text_reponse and $tree_response on success. These parameters are used later
- * by CASClient::validatePGT() for CAS proxies.
- * Used for all CAS 1.0 validations
- * @param $validate_url the URL of the request to the CAS server.
- * @param $text_response the response of the CAS server, as is (XML text).
- * @param $tree_response the response of the CAS server, as a DOM XML tree.
- *
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validateST($validate_url,&$text_response,&$tree_response)
- {
- phpCAS::traceBegin();
- // build the URL to validate the ticket
- $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST();
- if ( $this->isProxy() ) {
- // pass the callback url for CAS proxies
- $validate_url .= '&pgtUrl='.urlencode($this->getCallbackURL());
- }
-
- // open and read the URL
- if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
- $this->authError('ST not validated',
- $validate_url,
- TRUE/*$no_response*/);
- }
-
- // analyze the result depending on the version
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- if (preg_match('/^no\n/',$text_response)) {
- phpCAS::trace('ST has not been validated');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- }
- if (!preg_match('/^yes\n/',$text_response)) {
- phpCAS::trace('ill-formed response');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // ST has been validated, extract the user name
- $arr = preg_split('/\n/',$text_response);
- $this->setUser(trim($arr[1]));
- break;
- case CAS_VERSION_2_0:
- // read the response of the CAS server into a DOM object
- if ( !($dom = domxml_open_mem($text_response))) {
- phpCAS::trace('domxml_open_mem() failed');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // read the root node of the XML tree
- if ( !($tree_response = $dom->document_element()) ) {
- phpCAS::trace('document_element() failed');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // insure that tag name is 'serviceResponse'
- if ( $tree_response->node_name() != 'serviceResponse' ) {
- phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\'');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
- // authentication succeded, extract the user name
- if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) {
- phpCAS::trace('<authenticationSuccess> found, but no <user>');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- $user = trim($user_elements[0]->get_content());
- phpCAS::trace('user = `'.$user);
- $this->setUser($user);
-
- } else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
- phpCAS::trace('<authenticationFailure> found');
- // authentication failed, extract the error code and message
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response,
- $failure_elements[0]->get_attribute('code')/*$err_code*/,
- trim($failure_elements[0]->get_content())/*$err_msg*/);
- } else {
- phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- break;
- }
- $this->renameSession($this->getST());
- // at this step, ST has been validated and $this->_user has been set,
- phpCAS::traceEnd(TRUE);
- return TRUE;
- }
-
- // ########################################################################
- // SAML VALIDATION
- // ########################################################################
- /**
- * @addtogroup internalBasic
- * @{
- */
-
- /**
- * This method is used to validate a SAML TICKET; halt on failure, and sets $validate_url,
- * $text_reponse and $tree_response on success. These parameters are used later
- * by CASClient::validatePGT() for CAS proxies.
- *
- * @param $validate_url the URL of the request to the CAS server.
- * @param $text_response the response of the CAS server, as is (XML text).
- * @param $tree_response the response of the CAS server, as a DOM XML tree.
- *
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validateSA($validate_url,&$text_response,&$tree_response)
- {
- phpCAS::traceBegin();
-
- // build the URL to validate the ticket
- $validate_url = $this->getServerSamlValidateURL();
-
- // open and read the URL
- if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
- $this->authError('SA not validated', $validate_url, TRUE/*$no_response*/);
- }
-
- phpCAS::trace('server version: '.$this->getServerVersion());
-
- // analyze the result depending on the version
- switch ($this->getServerVersion()) {
- case SAML_VERSION_1_1:
-
- // read the response of the CAS server into a DOM object
- if ( !($dom = domxml_open_mem($text_response))) {
- phpCAS::trace('domxml_open_mem() failed');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // read the root node of the XML tree
- if ( !($tree_response = $dom->document_element()) ) {
- phpCAS::trace('document_element() failed');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // insure that tag name is 'Envelope'
- if ( $tree_response->node_name() != 'Envelope' ) {
- phpCAS::trace('bad XML root node (should be `Envelope\' instead of `'.$tree_response->node_name().'\'');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // check for the NameIdentifier tag in the SAML response
- if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("NameIdentifier")) != 0) {
- phpCAS::trace('NameIdentifier found');
- $user = trim($success_elements[0]->get_content());
- phpCAS::trace('user = `'.$user.'`');
- $this->setUser($user);
- $this->setSessionAttributes($text_response);
- } else {
- phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- break;
- }
- $this->renameSession($this->getSA());
- // at this step, ST has been validated and $this->_user has been set,
- phpCAS::traceEnd(TRUE);
- return TRUE;
- }
-
- /**
- * This method will parse the DOM and pull out the attributes from the SAML
- * payload and put them into an array, then put the array into the session.
- *
- * @param $text_response the SAML payload.
- * @return bool TRUE when successfull and FALSE if no attributes a found
- *
- * @private
- */
- function setSessionAttributes($text_response)
- {
- phpCAS::traceBegin();
-
- $result = FALSE;
-
- if (isset($_SESSION[SAML_ATTRIBUTES])) {
- phpCAS::trace("session attrs already set."); //testbml - do we care?
- }
-
- $attr_array = array();
-
- if (($dom = domxml_open_mem($text_response))) {
- $xPath = $dom->xpath_new_context();
- $xPath->xpath_register_ns('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
- $xPath->xpath_register_ns('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
- $nodelist = $xPath->xpath_eval("//saml:Attribute");
- if($nodelist){
- $attrs = $nodelist->nodeset;
- foreach($attrs as $attr){
- $xres = $xPath->xpath_eval("saml:AttributeValue", $attr);
- $name = $attr->get_attribute("AttributeName");
- $value_array = array();
- foreach($xres->nodeset as $node){
- $value_array[] = $node->get_content();
- }
- $attr_array[$name] = $value_array;
- }
- $_SESSION[SAML_ATTRIBUTES] = $attr_array;
- // UGent addition...
- foreach($attr_array as $attr_key => $attr_value) {
- if(count($attr_value) > 1) {
- $this->_attributes[$attr_key] = $attr_value;
- phpCAS::trace("* " . $attr_key . "=" . $attr_value);
- }
- else {
- $this->_attributes[$attr_key] = $attr_value[0];
- phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]);
- }
- }
- $result = TRUE;
- }else{
- phpCAS::trace("SAML Attributes are empty");
- $result = FALSE;
- }
- }
- phpCAS::traceEnd($result);
- return $result;
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX PROXY FEATURES (CAS 2.0) XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // PROXYING
- // ########################################################################
- /**
- * @addtogroup internalProxy
- * @{
- */
-
- /**
- * A boolean telling if the client is a CAS proxy or not. Written by CASClient::CASClient(),
- * read by CASClient::isProxy().
- *
- * @private
- */
- var $_proxy;
-
- /**
- * Tells if a CAS client is a CAS proxy or not
- *
- * @return TRUE when the CAS client is a CAs proxy, FALSE otherwise
- *
- * @private
- */
- function isProxy()
- {
- return $this->_proxy;
- }
-
- /** @} */
- // ########################################################################
- // PGT
- // ########################################################################
- /**
- * @addtogroup internalProxy
- * @{
- */
-
- /**
- * the Proxy Grnting Ticket given by the CAS server (empty otherwise).
- * Written by CASClient::setPGT(), read by CASClient::getPGT() and CASClient::hasPGT().
- *
- * @hideinitializer
- * @private
- */
- var $_pgt = '';
-
- /**
- * This method returns the Proxy Granting Ticket given by the CAS server.
- * @return The Proxy Granting Ticket.
- * @private
- */
- function getPGT()
- { return $this->_pgt; }
-
- /**
- * This method stores the Proxy Granting Ticket.
- * @param $pgt The Proxy Granting Ticket.
- * @private
- */
- function setPGT($pgt)
- { $this->_pgt = $pgt; }
-
- /**
- * This method tells if a Proxy Granting Ticket was stored.
- * @return TRUE if a Proxy Granting Ticket has been stored.
- * @private
- */
- function hasPGT()
- { return !empty($this->_pgt); }
-
- /** @} */
-
- // ########################################################################
- // CALLBACK MODE
- // ########################################################################
- /**
- * @addtogroup internalCallback
- * @{
- */
- /**
- * each PHP script using phpCAS in proxy mode is its own callback to get the
- * PGT back from the CAS server. callback_mode is detected by the constructor
- * thanks to the GET parameters.
- */
-
- /**
- * a boolean to know if the CAS client is running in callback mode. Written by
- * CASClient::setCallBackMode(), read by CASClient::isCallbackMode().
- *
- * @hideinitializer
- * @private
- */
- var $_callback_mode = FALSE;
-
- /**
- * This method sets/unsets callback mode.
- *
- * @param $callback_mode TRUE to set callback mode, FALSE otherwise.
- *
- * @private
- */
- function setCallbackMode($callback_mode)
- {
- $this->_callback_mode = $callback_mode;
- }
-
- /**
- * This method returns TRUE when the CAs client is running i callback mode,
- * FALSE otherwise.
- *
- * @return A boolean.
- *
- * @private
- */
- function isCallbackMode()
- {
- return $this->_callback_mode;
- }
-
- /**
- * the URL that should be used for the PGT callback (in fact the URL of the
- * current request without any CGI parameter). Written and read by
- * CASClient::getCallbackURL().
- *
- * @hideinitializer
- * @private
- */
- var $_callback_url = '';
-
- /**
- * This method returns the URL that should be used for the PGT callback (in
- * fact the URL of the current request without any CGI parameter, except if
- * phpCAS::setFixedCallbackURL() was used).
- *
- * @return The callback URL
- *
- * @private
- */
- function getCallbackURL()
- {
- // the URL is built when needed only
- if ( empty($this->_callback_url) ) {
- $final_uri = '';
- // remove the ticket if present in the URL
- $final_uri = 'https://';
- /* replaced by Julien Marchal - v0.4.6
- * $this->uri .= $_SERVER['SERVER_NAME'];
- */
- if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
- /* replaced by teedog - v0.4.12
- * $final_uri .= $_SERVER['SERVER_NAME'];
- */
- if (empty($_SERVER['SERVER_NAME'])) {
- $final_uri .= $_SERVER['HTTP_HOST'];
- } else {
- $final_uri .= $_SERVER['SERVER_NAME'];
- }
- } else {
- $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
- }
- if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
- || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
- $final_uri .= ':';
- $final_uri .= $_SERVER['SERVER_PORT'];
- }
- $request_uri = $_SERVER['REQUEST_URI'];
- $request_uri = preg_replace('/\?.*$/','',$request_uri);
- $final_uri .= $request_uri;
- $this->setCallbackURL($final_uri);
- }
- return $this->_callback_url;
- }
-
- /**
- * This method sets the callback url.
- *
- * @param $callback_url url to set callback
- *
- * @private
- */
- function setCallbackURL($url)
- {
- return $this->_callback_url = $url;
- }
-
- /**
- * This method is called by CASClient::CASClient() when running in callback
- * mode. It stores the PGT and its PGT Iou, prints its output and halts.
- *
- * @private
- */
- function callback()
- {
- phpCAS::traceBegin();
- $this->printHTMLHeader('phpCAS callback');
- $pgt_iou = $_GET['pgtIou'];
- $pgt = $_GET['pgtId'];
- phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
- echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
- $this->storePGT($pgt,$pgt_iou);
- $this->printHTMLFooter();
- phpCAS::traceExit();
- exit();
- }
-
- /** @} */
-
- // ########################################################################
- // PGT STORAGE
- // ########################################################################
- /**
- * @addtogroup internalPGTStorage
- * @{
- */
-
- /**
- * an instance of a class inheriting of PGTStorage, used to deal with PGT
- * storage. Created by CASClient::setPGTStorageFile() or CASClient::setPGTStorageDB(), used
- * by CASClient::setPGTStorageFile(), CASClient::setPGTStorageDB() and CASClient::initPGTStorage().
- *
- * @hideinitializer
- * @private
- */
- var $_pgt_storage = null;
-
- /**
- * This method is used to initialize the storage of PGT's.
- * Halts on error.
- *
- * @private
- */
- function initPGTStorage()
- {
- // if no SetPGTStorageXxx() has been used, default to file
- if ( !is_object($this->_pgt_storage) ) {
- $this->setPGTStorageFile();
- }
-
- // initializes the storage
- $this->_pgt_storage->init();
- }
-
- /**
- * This method stores a PGT. Halts on error.
- *
- * @param $pgt the PGT to store
- * @param $pgt_iou its corresponding Iou
- *
- * @private
- */
- function storePGT($pgt,$pgt_iou)
- {
- // ensure that storage is initialized
- $this->initPGTStorage();
- // writes the PGT
- $this->_pgt_storage->write($pgt,$pgt_iou);
- }
-
- /**
- * This method reads a PGT from its Iou and deletes the corresponding storage entry.
- *
- * @param $pgt_iou the PGT Iou
- *
- * @return The PGT corresponding to the Iou, FALSE when not found.
- *
- * @private
- */
- function loadPGT($pgt_iou)
- {
- // ensure that storage is initialized
- $this->initPGTStorage();
- // read the PGT
- return $this->_pgt_storage->read($pgt_iou);
- }
-
- /**
- * This method is used to tell phpCAS to store the response of the
- * CAS server to PGT requests onto the filesystem.
- *
- * @param $format the format used to store the PGT's (`plain' and `xml' allowed)
- * @param $path the path where the PGT's should be stored
- *
- * @public
- */
- function setPGTStorageFile($format='',
- $path='')
- {
- // check that the storage has not already been set
- if ( is_object($this->_pgt_storage) ) {
- phpCAS::error('PGT storage already defined');
- }
-
- // create the storage object
- $this->_pgt_storage = new PGTStorageFile($this,$format,$path);
- }
-
- /**
- * This method is used to tell phpCAS to store the response of the
- * CAS server to PGT requests into a database.
- * @note The connection to the database is done only when needed.
- * As a consequence, bad parameters are detected only when
- * initializing PGT storage.
- *
- * @param $user the user to access the data with
- * @param $password the user's password
- * @param $database_type the type of the database hosting the data
- * @param $hostname the server hosting the database
- * @param $port the port the server is listening on
- * @param $database the name of the database
- * @param $table the name of the table storing the data
- *
- * @public
- */
- function setPGTStorageDB($user,
- $password,
- $database_type,
- $hostname,
- $port,
- $database,
- $table)
- {
- // check that the storage has not already been set
- if ( is_object($this->_pgt_storage) ) {
- phpCAS::error('PGT storage already defined');
- }
-
- // warn the user that he should use file storage...
- trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
-
- // create the storage object
- $this->_pgt_storage = new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
- }
-
- // ########################################################################
- // PGT VALIDATION
- // ########################################################################
- /**
- * This method is used to validate a PGT; halt on failure.
- *
- * @param $validate_url the URL of the request to the CAS server.
- * @param $text_response the response of the CAS server, as is (XML text); result
- * of CASClient::validateST() or CASClient::validatePT().
- * @param $tree_response the response of the CAS server, as a DOM XML tree; result
- * of CASClient::validateST() or CASClient::validatePT().
- *
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validatePGT(&$validate_url,$text_response,$tree_response)
- {
- // here cannot use phpCAS::traceBegin(); alongside domxml-php4-to-php5.php
- phpCAS::log('start validatePGT()');
- if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
- phpCAS::trace('<proxyGrantingTicket> not found');
- // authentication succeded, but no PGT Iou was transmitted
- $this->authError('Ticket validated but no PGT Iou transmitted',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- } else {
- // PGT Iou transmitted, extract it
- $pgt_iou = trim($arr[0]->get_content());
- $pgt = $this->loadPGT($pgt_iou);
- if ( $pgt == FALSE ) {
- phpCAS::trace('could not load PGT');
- $this->authError('PGT Iou was transmitted but PGT could not be retrieved',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- }
- $this->setPGT($pgt);
- }
- // here, cannot use phpCAS::traceEnd(TRUE); alongside domxml-php4-to-php5.php
- phpCAS::log('end validatePGT()');
- return TRUE;
- }
-
- // ########################################################################
- // PGT VALIDATION
- // ########################################################################
-
- /**
- * This method is used to retrieve PT's from the CAS server thanks to a PGT.
- *
- * @param $target_service the service to ask for with the PT.
- * @param $err_code an error code (PHPCAS_SERVICE_OK on success).
- * @param $err_msg an error message (empty on success).
- *
- * @return a Proxy Ticket, or FALSE on error.
- *
- * @private
- */
- function retrievePT($target_service,&$err_code,&$err_msg)
- {
- phpCAS::traceBegin();
-
- // by default, $err_msg is set empty and $pt to TRUE. On error, $pt is
- // set to false and $err_msg to an error message. At the end, if $pt is FALSE
- // and $error_msg is still empty, it is set to 'invalid response' (the most
- // commonly encountered error).
- $err_msg = '';
-
- // build the URL to retrieve the PT
- // $cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT();
- $cas_url = $this->getServerProxyURL().'?targetService='.urlencode($target_service).'&pgt='.$this->getPGT();
-
- // open and read the URL
- if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
- $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
- $err_msg = 'could not retrieve PT (no response from the CAS server)';
- phpCAS::traceEnd(FALSE);
- return FALSE;
- }
-
- $bad_response = FALSE;
-
- if ( !$bad_response ) {
- // read the response of the CAS server into a DOM object
- if ( !($dom = @domxml_open_mem($cas_response))) {
- phpCAS::trace('domxml_open_mem() failed');
- // read failed
- $bad_response = TRUE;
- }
- }
-
- if ( !$bad_response ) {
- // read the root node of the XML tree
- if ( !($root = $dom->document_element()) ) {
- phpCAS::trace('document_element() failed');
- // read failed
- $bad_response = TRUE;
- }
- }
-
- if ( !$bad_response ) {
- // insure that tag name is 'serviceResponse'
- if ( $root->node_name() != 'serviceResponse' ) {
- phpCAS::trace('node_name() failed');
- // bad root node
- $bad_response = TRUE;
- }
- }
-
- if ( !$bad_response ) {
- // look for a proxySuccess tag
- if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
- // authentication succeded, look for a proxyTicket tag
- if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
- $err_code = PHPCAS_SERVICE_OK;
- $err_msg = '';
- phpCAS::trace('original PT: '.trim($arr[0]->get_content()));
- $pt = trim($arr[0]->get_content());
- phpCAS::traceEnd($pt);
- return $pt;
- } else {
- phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
- }
- }
- // look for a proxyFailure tag
- else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
- // authentication failed, extract the error
- $err_code = PHPCAS_SERVICE_PT_FAILURE;
- $err_msg = 'PT retrieving failed (code=`'
- .$arr[0]->get_attribute('code')
- .'\', message=`'
- .trim($arr[0]->get_content())
- .'\')';
- phpCAS::traceEnd(FALSE);
- return FALSE;
- } else {
- phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
- }
- }
-
- // at this step, we are sure that the response of the CAS server was ill-formed
- $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
- $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
-
- phpCAS::traceEnd(FALSE);
- return FALSE;
- }
-
- // ########################################################################
- // ACCESS TO EXTERNAL SERVICES
- // ########################################################################
-
- /**
- * This method is used to acces a remote URL.
- *
- * @param $url the URL to access.
- * @param $cookies an array containing cookies strings such as 'name=val'
- * @param $headers an array containing the HTTP header lines of the response
- * (an empty array on failure).
- * @param $body the body of the response, as a string (empty on failure).
- * @param $err_msg an error message, filled on failure.
- *
- * @return TRUE on success, FALSE otherwise (in this later case, $err_msg
- * contains an error message).
- *
- * @private
- */
- function readURL($url,$cookies,&$headers,&$body,&$err_msg)
- {
- phpCAS::traceBegin();
- $headers = '';
- $body = '';
- $err_msg = '';
-
- $res = TRUE;
-
- // initialize the CURL session
- $ch = curl_init($url);
-
- if (version_compare(PHP_VERSION,'5.1.3','>=')) {
- //only avaible in php5
- curl_setopt_array($ch, $this->_curl_options);
- } else {
- foreach ($this->_curl_options as $key => $value) {
- curl_setopt($ch, $key, $value);
- }
- }
-
- if ($this->_cas_server_cert == '' && $this->_cas_server_ca_cert == '' && !$this->_no_cas_server_validation) {
- phpCAS::error('one of the methods phpCAS::setCasServerCert(), phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.');
- }
- if ($this->_cas_server_cert != '' && $this->_cas_server_ca_cert != '') {
- // This branch added by IDMS. Seems phpCAS implementor got a bit confused about the curl options CURLOPT_SSLCERT and CURLOPT_CAINFO
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
- curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
- curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
- curl_setopt($ch, CURLOPT_VERBOSE, '1');
- phpCAS::trace('CURL: Set all required opts for mutual authentication ------');
- } else if ($this->_cas_server_cert != '' ) {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
- } else if ($this->_cas_server_ca_cert != '') {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
- } else {
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
- }
-
- // return the CURL output into a variable
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- // get the HTTP header with a callback
- $this->_curl_headers = array(); // empty the headers array
- curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curl_read_headers'));
- // add cookies headers
- if ( is_array($cookies) ) {
- curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
- }
- // add extra stuff if SAML
- if ($this->hasSA()) {
- $more_headers = array ("soapaction: http://www.oasis-open.org/committees/security",
- "cache-control: no-cache",
- "pragma: no-cache",
- "accept: text/xml",
- "connection: keep-alive",
- "content-type: text/xml");
-
- curl_setopt($ch, CURLOPT_HTTPHEADER, $more_headers);
- curl_setopt($ch, CURLOPT_POST, 1);
- $data = $this->buildSAMLPayload();
- //phpCAS::trace('SAML Payload: '.print_r($data, TRUE));
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
- }
- // perform the query
- $buf = curl_exec ($ch);
- //phpCAS::trace('CURL: Call completed. Response body is: \''.$buf.'\'');
- if ( $buf === FALSE ) {
- phpCAS::trace('curl_exec() failed');
- $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
- //phpCAS::trace('curl error: '.$err_msg);
- // close the CURL session
- curl_close ($ch);
- $res = FALSE;
- } else {
- // close the CURL session
- curl_close ($ch);
-
- $headers = $this->_curl_headers;
- $body = $buf;
- }
-
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method is used to build the SAML POST body sent to /samlValidate URL.
- *
- * @return the SOAP-encased SAMLP artifact (the ticket).
- *
- * @private
- */
- function buildSAMLPayload()
- {
- phpCAS::traceBegin();
-
- //get the ticket
- $sa = $this->getSA();
- //phpCAS::trace("SA: ".$sa);
-
- $body=SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST.SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE.SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
-
- phpCAS::traceEnd($body);
- return ($body);
- }
-
- /**
- * This method is the callback used by readURL method to request HTTP headers.
- */
- var $_curl_headers = array();
- function _curl_read_headers($ch, $header)
- {
- $this->_curl_headers[] = $header;
- return strlen($header);
- }
-
- /**
- * This method is used to access an HTTP[S] service.
- *
- * @param $url the service to access.
- * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
- * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
- * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.
- * @param $output the output of the service (also used to give an error
- * message on failure).
- *
- * @return TRUE on success, FALSE otherwise (in this later case, $err_code
- * gives the reason why it failed and $output contains an error message).
- *
- * @public
- */
- function serviceWeb($url,&$err_code,&$output)
- {
- phpCAS::traceBegin();
- $cookies = array();
- // at first retrieve a PT
- $pt = $this->retrievePT($url,$err_code,$output);
-
- $res = TRUE;
-
- // test if PT was retrieved correctly
- if ( !$pt ) {
- // note: $err_code and $err_msg are filled by CASClient::retrievePT()
- phpCAS::trace('PT was not retrieved correctly');
- $res = FALSE;
- } else {
- // add cookies if necessary
- if ( isset($_SESSION['phpCAS']['services'][$url]['cookies']) &&
- is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) {
- foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) {
- $cookies[] = $name.'='.$val;
- }
- }
-
- // build the URL including the PT
- if ( strstr($url,'?') === FALSE ) {
- $service_url = $url.'?ticket='.$pt;
- } else {
- $service_url = $url.'&ticket='.$pt;
- }
-
- phpCAS::trace('reading URL`'.$service_url.'\'');
- if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
- phpCAS::trace('could not read URL`'.$service_url.'\'');
- $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
- // give an error message
- $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
- $service_url,
- $err_msg);
- $res = FALSE;
- } else {
- // URL has been fetched, extract the cookies
- phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:');
- foreach ( $headers as $header ) {
- // test if the header is a cookie
- if ( preg_match('/^Set-Cookie:/',$header) ) {
- // the header is a cookie, remove the beginning
- $header_val = preg_replace('/^Set-Cookie: */','',$header);
- // extract interesting information
- $name_val = strtok($header_val,'; ');
- // extract the name and the value of the cookie
- $cookie_name = strtok($name_val,'=');
- $cookie_val = strtok('=');
- // store the cookie
- $_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
- phpCAS::trace($cookie_name.' -> '.$cookie_val);
- }
- }
- }
- }
-
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method is used to access an IMAP/POP3/NNTP service.
- *
- * @param $url a string giving the URL of the service, including the mailing box
- * for IMAP URLs, as accepted by imap_open().
- * @param $service a string giving for CAS retrieve Proxy ticket
- * @param $flags options given to imap_open().
- * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
- * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
- * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.
- * @param $err_msg an error message on failure
- * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL
- * on success, FALSE on error).
- *
- * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code
- * gives the reason why it failed and $err_msg contains an error message).
- *
- * @public
- */
- function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt)
- {
- phpCAS::traceBegin();
- // at first retrieve a PT
- $pt = $this->retrievePT($service,$err_code,$output);
-
- $stream = FALSE;
-
- // test if PT was retrieved correctly
- if ( !$pt ) {
- // note: $err_code and $err_msg are filled by CASClient::retrievePT()
- phpCAS::trace('PT was not retrieved correctly');
- } else {
- phpCAS::trace('opening IMAP URL `'.$url.'\'...');
- $stream = @imap_open($url,$this->getUser(),$pt,$flags);
- if ( !$stream ) {
- phpCAS::trace('could not open URL');
- $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
- // give an error message
- $err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
- $service_url,
- var_export(imap_errors(),TRUE));
- $pt = FALSE;
- $stream = FALSE;
- } else {
- phpCAS::trace('ok');
- }
- }
-
- phpCAS::traceEnd($stream);
- return $stream;
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX PROXIED CLIENT FEATURES (CAS 2.0) XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // PT
- // ########################################################################
- /**
- * @addtogroup internalProxied
- * @{
- */
-
- /**
- * the Proxy Ticket provided in the URL of the request if present
- * (empty otherwise). Written by CASClient::CASClient(), read by
- * CASClient::getPT() and CASClient::hasPGT().
- *
- * @hideinitializer
- * @private
- */
- var $_pt = '';
-
- /**
- * This method returns the Proxy Ticket provided in the URL of the request.
- * @return The proxy ticket.
- * @private
- */
- function getPT()
- {
- // return 'ST'.substr($this->_pt, 2);
- return $this->_pt;
- }
-
- /**
- * This method stores the Proxy Ticket.
- * @param $pt The Proxy Ticket.
- * @private
- */
- function setPT($pt)
- { $this->_pt = $pt; }
-
- /**
- * This method tells if a Proxy Ticket was stored.
- * @return TRUE if a Proxy Ticket has been stored.
- * @private
- */
- function hasPT()
- { return !empty($this->_pt); }
- /**
- * This method returns the SAML Ticket provided in the URL of the request.
- * @return The SAML ticket.
- * @private
- */
- function getSA()
- { return 'ST'.substr($this->_sa, 2); }
-
- /**
- * This method stores the SAML Ticket.
- * @param $sa The SAML Ticket.
- * @private
- */
- function setSA($sa)
- { $this->_sa = $sa; }
-
- /**
- * This method tells if a SAML Ticket was stored.
- * @return TRUE if a SAML Ticket has been stored.
- * @private
- */
- function hasSA()
- { return !empty($this->_sa); }
-
- /** @} */
- // ########################################################################
- // PT VALIDATION
- // ########################################################################
- /**
- * @addtogroup internalProxied
- * @{
- */
-
- /**
- * This method is used to validate a ST or PT; halt on failure
- * Used for all CAS 2.0 validations
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validatePT(&$validate_url,&$text_response,&$tree_response)
- {
- phpCAS::traceBegin();
- // build the URL to validate the ticket
- $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT();
-
- if ( $this->isProxy() ) {
- // pass the callback url for CAS proxies
- $validate_url .= '&pgtUrl='.urlencode($this->getCallbackURL());
- }
-
- // open and read the URL
- if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
- $this->authError('PT not validated',
- $validate_url,
- TRUE/*$no_response*/);
- }
-
- // read the response of the CAS server into a DOM object
- if ( !($dom = domxml_open_mem($text_response))) {
- // read failed
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // read the root node of the XML tree
- if ( !($tree_response = $dom->document_element()) ) {
- // read failed
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // insure that tag name is 'serviceResponse'
- if ( $tree_response->node_name() != 'serviceResponse' ) {
- // bad root node
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
- // authentication succeded, extract the user name
- if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
- // no user specified => error
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- $this->setUser(trim($arr[0]->get_content()));
-
- } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
- // authentication succeded, extract the error code and message
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response,
- $arr[0]->get_attribute('code')/*$err_code*/,
- trim($arr[0]->get_content())/*$err_msg*/);
- } else {
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
-
- $this->renameSession($this->getPT());
- // at this step, PT has been validated and $this->_user has been set,
-
- phpCAS::traceEnd(TRUE);
- return TRUE;
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX MISC XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- /**
- * @addtogroup internalMisc
- * @{
- */
-
- // ########################################################################
- // URL
- // ########################################################################
- /**
- * the URL of the current request (without any ticket CGI parameter). Written
- * and read by CASClient::getURL().
- *
- * @hideinitializer
- * @private
- */
- var $_url = '';
-
- /**
- * This method returns the URL of the current request (without any ticket
- * CGI parameter).
- *
- * @return The URL
- *
- * @private
- */
- function getURL()
- {
- phpCAS::traceBegin();
- // the URL is built when needed only
- if ( empty($this->_url) ) {
- $final_uri = '';
- // remove the ticket if present in the URL
- $final_uri = ($this->isHttps()) ? 'https' : 'http';
- $final_uri .= '://';
- /* replaced by Julien Marchal - v0.4.6
- * $this->_url .= $_SERVER['SERVER_NAME'];
- */
- if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
- /* replaced by teedog - v0.4.12
- * $this->_url .= $_SERVER['SERVER_NAME'];
- */
- if (empty($_SERVER['SERVER_NAME'])) {
- $server_name = $_SERVER['HTTP_HOST'];
- } else {
- $server_name = $_SERVER['SERVER_NAME'];
- }
- } else {
- $server_name = $_SERVER['HTTP_X_FORWARDED_SERVER'];
- }
- $final_uri .= $server_name;
- if (!strpos($server_name, ':')) {
- if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
- || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
- $final_uri .= ':';
- $final_uri .= $_SERVER['SERVER_PORT'];
- }
- }
-
- $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2);
- $final_uri .= $request_uri[0];
-
- if (isset($request_uri[1]) && $request_uri[1])
- {
- $query_string = $this->removeParameterFromQueryString('ticket', $request_uri[1]);
-
- // If the query string still has anything left, append it to the final URI
- if ($query_string !== '')
- $final_uri .= "?$query_string";
-
- }
-
- phpCAS::trace("Final URI: $final_uri");
- $this->setURL($final_uri);
- }
- phpCAS::traceEnd($this->_url);
- return $this->_url;
- }
-
-
-
- /**
- * Removes a parameter from a query string
- *
- * @param string $parameterName
- * @param string $queryString
- * @return string
- *
- * @link http://stackoverflow.com/questions/1842681/regular-expression-to-remove-one-parameter-from-query-string
- */
- function removeParameterFromQueryString($parameterName, $queryString)
- {
- $parameterName = preg_quote($parameterName);
- return preg_replace("/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/", '', $queryString);
- }
-
-
- /**
- * This method sets the URL of the current request
- *
- * @param $url url to set for service
- *
- * @private
- */
- function setURL($url)
- {
- $this->_url = $url;
- }
-
- // ########################################################################
- // AUTHENTICATION ERROR HANDLING
- // ########################################################################
- /**
- * This method is used to print the HTML output when the user was not authenticated.
- *
- * @param $failure the failure that occured
- * @param $cas_url the URL the CAS server was asked for
- * @param $no_response the response from the CAS server (other
- * parameters are ignored if TRUE)
- * @param $bad_response bad response from the CAS server ($err_code
- * and $err_msg ignored if TRUE)
- * @param $cas_response the response of the CAS server
- * @param $err_code the error code given by the CAS server
- * @param $err_msg the error message given by the CAS server
- *
- * @private
- */
- function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
- {
- phpCAS::traceBegin();
-
- $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED));
- printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),htmlentities($this->getURL()),$_SERVER['SERVER_ADMIN']);
- phpCAS::trace('CAS URL: '.$cas_url);
- phpCAS::trace('Authentication failure: '.$failure);
- if ( $no_response ) {
- phpCAS::trace('Reason: no response from the CAS server');
- } else {
- if ( $bad_response ) {
- phpCAS::trace('Reason: bad response from the CAS server');
- } else {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- phpCAS::trace('Reason: CAS error');
- break;
- case CAS_VERSION_2_0:
- if ( empty($err_code) )
- phpCAS::trace('Reason: no CAS error');
- else
- phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
- break;
- }
- }
- phpCAS::trace('CAS response: '.$cas_response);
- }
- $this->printHTMLFooter();
- phpCAS::traceExit();
- exit();
- }
-
- /** @} */
-}
-
-?>
+++ /dev/null
-<?php
-/*
- Requires PHP5, uses built-in DOM extension.
- To be used in PHP4 scripts using DOMXML extension: allows PHP4/DOMXML scripts to run on PHP5/DOM.
- (Optional: requires PHP5/XSL extension for domxml_xslt functions, PHP>=5.1 for XPath evaluation functions, and PHP>=5.1/libxml for DOMXML error reports)
-
- Typical use:
- {
- if (PHP_VERSION>='5')
- require_once('domxml-php4-to-php5.php');
- }
-
- Version 1.21, 2008-12-05, http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/
-
- ------------------------------------------------------------------
- Written by Alexandre Alapetite, http://alexandre.alapetite.net/cv/
-
- Copyright 2004-2008, GNU Lesser General Public License,
- http://www.gnu.org/licenses/lgpl.html
-
- This program 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 3 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 Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/lgpl.html>
-
- == Rights and obligations ==
- - Attribution: You must give the original author credit.
- - Share Alike: If you alter or transform this library,
- you may distribute the resulting library only under the same license GNU/LGPL.
- - In case of jurisdiction dispute, the French law is authoritative.
- - Any of these conditions can be waived if you get permission from Alexandre Alapetite.
- - Not required, but please send to Alexandre Alapetite the modifications you make,
- in order to improve this file for the benefit of everybody.
-
- If you want to distribute this code, please do it as a link to:
- http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/
-*/
-
-define('DOMXML_LOAD_PARSING',0);
-define('DOMXML_LOAD_VALIDATING',1);
-define('DOMXML_LOAD_RECOVERING',2);
-define('DOMXML_LOAD_SUBSTITUTE_ENTITIES',4);
-//define('DOMXML_LOAD_COMPLETE_ATTRS',8);
-define('DOMXML_LOAD_DONT_KEEP_BLANKS',16);
-
-function domxml_new_doc($version) {return new php4DOMDocument();}
-function domxml_new_xmldoc($version) {return new php4DOMDocument();}
-function domxml_open_file($filename,$mode=DOMXML_LOAD_PARSING,&$error=null)
-{
- $dom=new php4DOMDocument($mode);
- $errorMode=(func_num_args()>2)&&defined('LIBXML_VERSION');
- if ($errorMode) libxml_use_internal_errors(true);
- if (!$dom->myDOMNode->load($filename)) $dom=null;
- if ($errorMode)
- {
- $error=array_map('_error_report',libxml_get_errors());
- libxml_clear_errors();
- }
- return $dom;
-}
-function domxml_open_mem($str,$mode=DOMXML_LOAD_PARSING,&$error=null)
-{
- $dom=new php4DOMDocument($mode);
- $errorMode=(func_num_args()>2)&&defined('LIBXML_VERSION');
- if ($errorMode) libxml_use_internal_errors(true);
- if (!$dom->myDOMNode->loadXML($str)) $dom=null;
- if ($errorMode)
- {
- $error=array_map('_error_report',libxml_get_errors());
- libxml_clear_errors();
- }
- return $dom;
-}
-function html_doc($html_doc,$from_file=false)
-{
- $dom=new php4DOMDocument();
- if ($from_file) $result=$dom->myDOMNode->loadHTMLFile($html_doc);
- else $result=$dom->myDOMNode->loadHTML($html_doc);
- return $result ? $dom : null;
-}
-function html_doc_file($filename) {return html_doc($filename,true);}
-function xmldoc($str) {return domxml_open_mem($str);}
-function xmldocfile($filename) {return domxml_open_file($filename);}
-function xpath_eval($xpath_context,$eval_str,$contextnode=null) {return $xpath_context->xpath_eval($eval_str,$contextnode);}
-function xpath_new_context($dom_document) {return new php4DOMXPath($dom_document);}
-function xpath_register_ns($xpath_context,$prefix,$namespaceURI) {return $xpath_context->myDOMXPath->registerNamespace($prefix,$namespaceURI);}
-function _entityDecode($text) {return html_entity_decode(strtr($text,array('''=>'\'')),ENT_QUOTES,'UTF-8');}
-function _error_report($error) {return array('errormessage'=>$error->message,'nodename'=>'','line'=>$error->line,'col'=>$error->column)+($error->file==''?array():array('directory'=>dirname($error->file),'file'=>basename($error->file)));}
-
-class php4DOMAttr extends php4DOMNode
-{
- function __get($name)
- {
- if ($name==='name') return $this->myDOMNode->name;
- else return parent::__get($name);
- }
- function name() {return $this->myDOMNode->name;}
- function set_content($text) {}
- //function set_value($content) {return $this->myDOMNode->value=htmlspecialchars($content,ENT_QUOTES);}
- function specified() {return $this->myDOMNode->specified;}
- function value() {return $this->myDOMNode->value;}
-}
-
-class php4DOMDocument extends php4DOMNode
-{
- function php4DOMDocument($mode=DOMXML_LOAD_PARSING)
- {
- $this->myDOMNode=new DOMDocument();
- $this->myOwnerDocument=$this;
- if ($mode & DOMXML_LOAD_VALIDATING) $this->myDOMNode->validateOnParse=true;
- if ($mode & DOMXML_LOAD_RECOVERING) $this->myDOMNode->recover=true;
- if ($mode & DOMXML_LOAD_SUBSTITUTE_ENTITIES) $this->myDOMNode->substituteEntities=true;
- if ($mode & DOMXML_LOAD_DONT_KEEP_BLANKS) $this->myDOMNode->preserveWhiteSpace=false;
- }
- function add_root($name)
- {
- if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild);
- return new php4DOMElement($this->myDOMNode->appendChild($this->myDOMNode->createElement($name)),$this->myOwnerDocument);
- }
- function create_attribute($name,$value)
- {
- $myAttr=$this->myDOMNode->createAttribute($name);
- $myAttr->value=htmlspecialchars($value,ENT_QUOTES);
- return new php4DOMAttr($myAttr,$this);
- }
- function create_cdata_section($content) {return new php4DOMNode($this->myDOMNode->createCDATASection($content),$this);}
- function create_comment($data) {return new php4DOMNode($this->myDOMNode->createComment($data),$this);}
- function create_element($name) {return new php4DOMElement($this->myDOMNode->createElement($name),$this);}
- function create_element_ns($uri,$name,$prefix=null)
- {
- if ($prefix==null) $prefix=$this->myDOMNode->lookupPrefix($uri);
- if (($prefix==null)&&(($this->myDOMNode->documentElement==null)||(!$this->myDOMNode->documentElement->isDefaultNamespace($uri)))) $prefix='a'.sprintf('%u',crc32($uri));
- return new php4DOMElement($this->myDOMNode->createElementNS($uri,$prefix==null ? $name : $prefix.':'.$name),$this);
- }
- function create_entity_reference($content) {return new php4DOMNode($this->myDOMNode->createEntityReference($content),$this);} //By Walter Ebert 2007-01-22
- function create_processing_instruction($target,$data=''){return new php4DomProcessingInstruction($this->myDOMNode->createProcessingInstruction($target,$data),$this);}
- function create_text_node($content) {return new php4DOMText($this->myDOMNode->createTextNode($content),$this);}
- function document_element() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);}
- function dump_file($filename,$compressionmode=false,$format=false)
- {
- $format0=$this->myDOMNode->formatOutput;
- $this->myDOMNode->formatOutput=$format;
- $res=$this->myDOMNode->save($filename);
- $this->myDOMNode->formatOutput=$format0;
- return $res;
- }
- function dump_mem($format=false,$encoding=false)
- {
- $format0=$this->myDOMNode->formatOutput;
- $this->myDOMNode->formatOutput=$format;
- $encoding0=$this->myDOMNode->encoding;
- if ($encoding) $this->myDOMNode->encoding=$encoding;
- $dump=$this->myDOMNode->saveXML();
- $this->myDOMNode->formatOutput=$format0;
- if ($encoding) $this->myDOMNode->encoding= $encoding0=='' ? 'UTF-8' : $encoding0; //UTF-8 is XML default encoding
- return $dump;
- }
- function free()
- {
- if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild);
- $this->myDOMNode=null;
- $this->myOwnerDocument=null;
- }
- function get_element_by_id($id) {return parent::_newDOMElement($this->myDOMNode->getElementById($id),$this);}
- function get_elements_by_tagname($name)
- {
- $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name);
- $nodeSet=array();
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this);
- return $nodeSet;
- }
- function html_dump_mem() {return $this->myDOMNode->saveHTML();}
- function root() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);}
- function xinclude() {return $this->myDOMNode->xinclude();}
- function xpath_new_context() {return new php4DOMXPath($this);}
-}
-
-class php4DOMElement extends php4DOMNode
-{
- function add_namespace($uri,$prefix)
- {
- if ($this->myDOMNode->hasAttributeNS('http://www.w3.org/2000/xmlns/',$prefix)) return false;
- else
- {
- $this->myDOMNode->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:'.$prefix,$uri); //By Daniel Walker 2006-09-08
- return true;
- }
- }
- function get_attribute($name) {return $this->myDOMNode->getAttribute($name);}
- function get_attribute_node($name) {return parent::_newDOMElement($this->myDOMNode->getAttributeNode($name),$this->myOwnerDocument);}
- function get_elements_by_tagname($name)
- {
- $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name);
- $nodeSet=array();
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument);
- return $nodeSet;
- }
- function has_attribute($name) {return $this->myDOMNode->hasAttribute($name);}
- function remove_attribute($name) {return $this->myDOMNode->removeAttribute($name);}
- function set_attribute($name,$value)
- {
- //return $this->myDOMNode->setAttribute($name,$value); //Does not return a DomAttr
- $myAttr=$this->myDOMNode->ownerDocument->createAttribute($name);
- $myAttr->value=htmlspecialchars($value,ENT_QUOTES); //Entity problem reported by AL-DesignWorks 2007-09-07
- $this->myDOMNode->setAttributeNode($myAttr);
- return new php4DOMAttr($myAttr,$this->myOwnerDocument);
- }
- /*function set_attribute_node($attr)
- {
- $this->myDOMNode->setAttributeNode($this->_importNode($attr));
- return $attr;
- }*/
- function set_name($name)
- {
- if ($this->myDOMNode->prefix=='') $newNode=$this->myDOMNode->ownerDocument->createElement($name);
- else $newNode=$this->myDOMNode->ownerDocument->createElementNS($this->myDOMNode->namespaceURI,$this->myDOMNode->prefix.':'.$name);
- $myDOMNodeList=$this->myDOMNode->attributes;
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++))
- if ($node->namespaceURI=='') $newNode->setAttribute($node->name,$node->value);
- else $newNode->setAttributeNS($node->namespaceURI,$node->nodeName,$node->value);
- $myDOMNodeList=$this->myDOMNode->childNodes;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item(0)) $newNode->appendChild($node);
- $this->myDOMNode->parentNode->replaceChild($newNode,$this->myDOMNode);
- $this->myDOMNode=$newNode;
- return true;
- }
- function tagname() {return $this->tagname;}
-}
-
-class php4DOMNode
-{
- public $myDOMNode;
- public $myOwnerDocument;
- function php4DOMNode($aDomNode,$aOwnerDocument)
- {
- $this->myDOMNode=$aDomNode;
- $this->myOwnerDocument=$aOwnerDocument;
- }
- function __get($name)
- {
- switch ($name)
- {
- case 'type': return $this->myDOMNode->nodeType;
- case 'tagname': return ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->tagName; //Avoid namespace prefix for DOMElement
- case 'content': return $this->myDOMNode->textContent;
- case 'value': return $this->myDOMNode->value;
- default:
- $myErrors=debug_backtrace();
- trigger_error('Undefined property: '.get_class($this).'::$'.$name.' ['.$myErrors[0]['file'].':'.$myErrors[0]['line'].']',E_USER_NOTICE);
- return false;
- }
- }
- function add_child($newnode) {return append_child($newnode);}
- function add_namespace($uri,$prefix) {return false;}
- function append_child($newnode) {return self::_newDOMElement($this->myDOMNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);}
- function append_sibling($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);}
- function attributes()
- {
- $myDOMNodeList=$this->myDOMNode->attributes;
- if (!(isset($myDOMNodeList)&&$this->myDOMNode->hasAttributes())) return null;
- $nodeSet=array();
- $i=0;
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMAttr($node,$this->myOwnerDocument);
- return $nodeSet;
- }
- function child_nodes()
- {
- $myDOMNodeList=$this->myDOMNode->childNodes;
- $nodeSet=array();
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=self::_newDOMElement($node,$this->myOwnerDocument);
- return $nodeSet;
- }
- function children() {return $this->child_nodes();}
- function clone_node($deep=false) {return self::_newDOMElement($this->myDOMNode->cloneNode($deep),$this->myOwnerDocument);}
- //dump_node($node) should only be called on php4DOMDocument
- function dump_node($node=null) {return $node==null ? $this->myOwnerDocument->myDOMNode->saveXML($this->myDOMNode) : $this->myOwnerDocument->myDOMNode->saveXML($node->myDOMNode);}
- function first_child() {return self::_newDOMElement($this->myDOMNode->firstChild,$this->myOwnerDocument);}
- function get_content() {return $this->myDOMNode->textContent;}
- function has_attributes() {return $this->myDOMNode->hasAttributes();}
- function has_child_nodes() {return $this->myDOMNode->hasChildNodes();}
- function insert_before($newnode,$refnode) {return self::_newDOMElement($this->myDOMNode->insertBefore($this->_importNode($newnode),$refnode==null?null:$refnode->myDOMNode),$this->myOwnerDocument);}
- function is_blank_node() {return ($this->myDOMNode->nodeType===XML_TEXT_NODE)&&preg_match('%^\s*$%',$this->myDOMNode->nodeValue);}
- function last_child() {return self::_newDOMElement($this->myDOMNode->lastChild,$this->myOwnerDocument);}
- function new_child($name,$content)
- {
- $mySubNode=$this->myDOMNode->ownerDocument->createElement($name);
- $mySubNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(_entityDecode($content)));
- $this->myDOMNode->appendChild($mySubNode);
- return new php4DOMElement($mySubNode,$this->myOwnerDocument);
- }
- function next_sibling() {return self::_newDOMElement($this->myDOMNode->nextSibling,$this->myOwnerDocument);}
- function node_name() {return ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->nodeName;} //Avoid namespace prefix for DOMElement
- function node_type() {return $this->myDOMNode->nodeType;}
- function node_value() {return $this->myDOMNode->nodeValue;}
- function owner_document() {return $this->myOwnerDocument;}
- function parent_node() {return self::_newDOMElement($this->myDOMNode->parentNode,$this->myOwnerDocument);}
- function prefix() {return $this->myDOMNode->prefix;}
- function previous_sibling() {return self::_newDOMElement($this->myDOMNode->previousSibling,$this->myOwnerDocument);}
- function remove_child($oldchild) {return self::_newDOMElement($this->myDOMNode->removeChild($oldchild->myDOMNode),$this->myOwnerDocument);}
- function replace_child($newnode,$oldnode) {return self::_newDOMElement($this->myDOMNode->replaceChild($this->_importNode($newnode),$oldnode->myDOMNode),$this->myOwnerDocument);}
- function replace_node($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->replaceChild($this->_importNode($newnode),$this->myDOMNode),$this->myOwnerDocument);}
- function set_content($text) {return $this->myDOMNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(_entityDecode($text)));} //Entity problem reported by AL-DesignWorks 2007-09-07
- //function set_name($name) {return $this->myOwnerDocument->renameNode($this->myDOMNode,$this->myDOMNode->namespaceURI,$name);}
- function set_namespace($uri,$prefix=null)
- {//Contributions by Daniel Walker 2006-09-08
- $nsprefix=$this->myDOMNode->lookupPrefix($uri);
- if ($nsprefix==null)
- {
- $nsprefix= $prefix==null ? $nsprefix='a'.sprintf('%u',crc32($uri)) : $prefix;
- if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE)
- {
- if (($prefix!=null)&&$this->myDOMNode->ownerElement->hasAttributeNS('http://www.w3.org/2000/xmlns/',$nsprefix)&&
- ($this->myDOMNode->ownerElement->getAttributeNS('http://www.w3.org/2000/xmlns/',$nsprefix)!=$uri))
- {//Remove namespace
- $parent=$this->myDOMNode->ownerElement;
- $parent->removeAttributeNode($this->myDOMNode);
- $parent->setAttribute($this->myDOMNode->localName,$this->myDOMNode->nodeValue);
- $this->myDOMNode=$parent->getAttributeNode($this->myDOMNode->localName);
- return;
- }
- $this->myDOMNode->ownerElement->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:'.$nsprefix,$uri);
- }
- }
- if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE)
- {
- $parent=$this->myDOMNode->ownerElement;
- $parent->removeAttributeNode($this->myDOMNode);
- $parent->setAttributeNS($uri,$nsprefix.':'.$this->myDOMNode->localName,$this->myDOMNode->nodeValue);
- $this->myDOMNode=$parent->getAttributeNodeNS($uri,$this->myDOMNode->localName);
- }
- elseif ($this->myDOMNode->nodeType===XML_ELEMENT_NODE)
- {
- $NewNode=$this->myDOMNode->ownerDocument->createElementNS($uri,$nsprefix.':'.$this->myDOMNode->localName);
- foreach ($this->myDOMNode->attributes as $n) $NewNode->appendChild($n->cloneNode(true));
- foreach ($this->myDOMNode->childNodes as $n) $NewNode->appendChild($n->cloneNode(true));
- $xpath=new DOMXPath($this->myDOMNode->ownerDocument);
- $myDOMNodeList=$xpath->query('namespace::*[name()!="xml"]',$this->myDOMNode); //Add old namespaces
- foreach ($myDOMNodeList as $n) $NewNode->setAttributeNS('http://www.w3.org/2000/xmlns/',$n->nodeName,$n->nodeValue);
- $this->myDOMNode->parentNode->replaceChild($NewNode,$this->myDOMNode);
- $this->myDOMNode=$NewNode;
- }
- }
- function unlink_node()
- {
- if ($this->myDOMNode->parentNode!=null)
- {
- if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE) $this->myDOMNode->parentNode->removeAttributeNode($this->myDOMNode);
- else $this->myDOMNode->parentNode->removeChild($this->myDOMNode);
- }
- }
- protected function _importNode($newnode) {return $this->myOwnerDocument===$newnode->myOwnerDocument ? $newnode->myDOMNode : $this->myOwnerDocument->myDOMNode->importNode($newnode->myDOMNode,true);} //To import DOMNode from another DOMDocument
- static function _newDOMElement($aDOMNode,$aOwnerDocument)
- {//Check the PHP5 DOMNode before creating a new associated PHP4 DOMNode wrapper
- if ($aDOMNode==null) return null;
- switch ($aDOMNode->nodeType)
- {
- case XML_ELEMENT_NODE: return new php4DOMElement($aDOMNode,$aOwnerDocument);
- case XML_TEXT_NODE: return new php4DOMText($aDOMNode,$aOwnerDocument);
- case XML_ATTRIBUTE_NODE: return new php4DOMAttr($aDOMNode,$aOwnerDocument);
- case XML_PI_NODE: return new php4DomProcessingInstruction($aDOMNode,$aOwnerDocument);
- default: return new php4DOMNode($aDOMNode,$aOwnerDocument);
- }
- }
-}
-
-class php4DomProcessingInstruction extends php4DOMNode
-{
- function data() {return $this->myDOMNode->data;}
- function target() {return $this->myDOMNode->target;}
-}
-
-class php4DOMText extends php4DOMNode
-{
- function __get($name)
- {
- if ($name==='tagname') return '#text';
- else return parent::__get($name);
- }
- function tagname() {return '#text';}
- function set_content($text) {$this->myDOMNode->nodeValue=$text; return true;}
-}
-
-if (!defined('XPATH_NODESET'))
-{
- define('XPATH_UNDEFINED',0);
- define('XPATH_NODESET',1);
- define('XPATH_BOOLEAN',2);
- define('XPATH_NUMBER',3);
- define('XPATH_STRING',4);
- /*define('XPATH_POINT',5);
- define('XPATH_RANGE',6);
- define('XPATH_LOCATIONSET',7);
- define('XPATH_USERS',8);
- define('XPATH_XSLT_TREE',9);*/
-}
-
-class php4DOMNodelist
-{
- private $myDOMNodelist;
- public $nodeset;
- public $type=XPATH_UNDEFINED;
- public $value;
- function php4DOMNodelist($aDOMNodelist,$aOwnerDocument)
- {
- if (!isset($aDOMNodelist)) return;
- elseif (is_object($aDOMNodelist)||is_array($aDOMNodelist))
- {
- if ($aDOMNodelist->length>0)
- {
- $this->myDOMNodelist=$aDOMNodelist;
- $this->nodeset=array();
- $this->type=XPATH_NODESET;
- $i=0;
- while ($node=$this->myDOMNodelist->item($i++)) $this->nodeset[]=php4DOMNode::_newDOMElement($node,$aOwnerDocument);
- }
- }
- elseif (is_int($aDOMNodelist)||is_float($aDOMNodelist))
- {
- $this->type=XPATH_NUMBER;
- $this->value=$aDOMNodelist;
- }
- elseif (is_bool($aDOMNodelist))
- {
- $this->type=XPATH_BOOLEAN;
- $this->value=$aDOMNodelist;
- }
- elseif (is_string($aDOMNodelist))
- {
- $this->type=XPATH_STRING;
- $this->value=$aDOMNodelist;
- }
- }
-}
-
-class php4DOMXPath
-{
- public $myDOMXPath;
- private $myOwnerDocument;
- function php4DOMXPath($dom_document)
- {
- //TODO: If $dom_document is a DomElement, make that default $contextnode and modify XPath. Ex: '/test'
- $this->myOwnerDocument=$dom_document->myOwnerDocument;
- $this->myDOMXPath=new DOMXPath($this->myOwnerDocument->myDOMNode);
- }
- function xpath_eval($eval_str,$contextnode=null)
- {
- if (method_exists($this->myDOMXPath,'evaluate')) $xp=isset($contextnode) ? $this->myDOMXPath->evaluate($eval_str,$contextnode->myDOMNode) : $this->myDOMXPath->evaluate($eval_str);
- else $xp=isset($contextnode) ? $this->myDOMXPath->query($eval_str,$contextnode->myDOMNode) : $this->myDOMXPath->query($eval_str);
- $xp=new php4DOMNodelist($xp,$this->myOwnerDocument);
- return ($xp->type===XPATH_UNDEFINED) ? false : $xp;
- }
- function xpath_register_ns($prefix,$namespaceURI) {return $this->myDOMXPath->registerNamespace($prefix,$namespaceURI);}
-}
-
-if (extension_loaded('xsl'))
-{//See also: http://alexandre.alapetite.net/doc-alex/xslt-php4-php5/
- function domxml_xslt_stylesheet($xslstring) {return new php4DomXsltStylesheet(DOMDocument::loadXML($xslstring));}
- function domxml_xslt_stylesheet_doc($dom_document) {return new php4DomXsltStylesheet($dom_document);}
- function domxml_xslt_stylesheet_file($xslfile) {return new php4DomXsltStylesheet(DOMDocument::load($xslfile));}
- class php4DomXsltStylesheet
- {
- private $myxsltProcessor;
- function php4DomXsltStylesheet($dom_document)
- {
- $this->myxsltProcessor=new xsltProcessor();
- $this->myxsltProcessor->importStyleSheet($dom_document);
- }
- function process($dom_document,$xslt_parameters=array(),$param_is_xpath=false)
- {
- foreach ($xslt_parameters as $param=>$value) $this->myxsltProcessor->setParameter('',$param,$value);
- $myphp4DOMDocument=new php4DOMDocument();
- $myphp4DOMDocument->myDOMNode=$this->myxsltProcessor->transformToDoc($dom_document->myDOMNode);
- return $myphp4DOMDocument;
- }
- function result_dump_file($dom_document,$filename)
- {
- $html=$dom_document->myDOMNode->saveHTML();
- file_put_contents($filename,$html);
- return $html;
- }
- function result_dump_mem($dom_document) {return $dom_document->myDOMNode->saveHTML();}
- }
-}
-?>
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/spanish.php\r
- * @author Iván-Benjamín García Torà <ivaniclixx AT gmail DOT com>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'usant servidor',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'Autentificació CAS necessària!',\r
- CAS_STR_LOGOUT \r
- => 'Sortida de CAS necessària!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click <a href="%s">aquí</a> per a continuar.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'Autentificació CAS fallida!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>No estàs autentificat.</p><p>Pots tornar a intentar-ho fent click <a href="%s">aquí</a>.</p><p>Si el problema persisteix hauría de contactar amb l\'<a href="mailto:%s">administrador d\'aquest llocc</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'El servei `<b>%s</b>\' no està disponible (<b>%s</b>).'\r
-);\r
-\r
-?>\r
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/english.php\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'using server',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'CAS Authentication wanted!',\r
- CAS_STR_LOGOUT \r
- => 'CAS logout wanted!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'You should already have been redirected to the CAS server. Click <a href="%s">here</a> to continue.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'CAS Authentication failed!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>You were not authenticated.</p><p>You may submit your request again by clicking <a href="%s">here</a>.</p><p>If the problem persists, you may contact <a href="mailto:%s">the administrator of this site</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'The service `<b>%s</b>\' is not available (<b>%s</b>).'\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/english.php\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'utilisant le serveur',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'Authentication CAS n�cessaire !',\r
- CAS_STR_LOGOUT \r
- => 'D�connexion demand�e !',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'Vous auriez du etre redirig�(e) vers le serveur CAS. Cliquez <a href="%s">ici</a> pour continuer.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'Authentification CAS infructueuse !',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>Vous n\'avez pas �t� authentifi�(e).</p><p>Vous pouvez soumettre votre requete � nouveau en cliquant <a href="%s">ici</a>.</p><p>Si le probl�me persiste, vous pouvez contacter <a href="mailto:%s">l\'administrateur de ce site</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'Le service `<b>%s</b>\' est indisponible (<b>%s</b>)'\r
-\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/german.php\r
- * @author Henrik Genssen <hg at mediafactory.de>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'via Server',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'CAS Authentifizierung erforderlich!',\r
- CAS_STR_LOGOUT \r
- => 'CAS Abmeldung!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie <a href="%s">hier</a> um fortzufahren.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'CAS Anmeldung fehlgeschlagen!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>Sie wurden nicht angemeldet.</p><p>Um es erneut zu versuchen klicken Sie <a href="%s">hier</a>.</p><p>Wenn das Problem bestehen bleibt, kontkatieren Sie den <a href="mailto:%s">Administrator</a> dieser Seite.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'Der Dienst `<b>%s</b>\' ist nicht verfügbar (<b>%s</b>).'\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/greek.php\r
- * @author Vangelis Haniotakis <haniotak at ucnet.uoc.gr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => '��������������� � ������������',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => '���������� � ����������� CAS!',\r
- CAS_STR_LOGOUT \r
- => '���������� � ���������� ��� CAS!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => '�� ������ �� ������ �������������� ���� ����������� CAS. ����� ���� <a href="%s">���</a> ��� �� ����������.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => '� ����������� CAS �������!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>��� ���������������.</p><p>�������� �� ����������������, �������� ���� <a href="%s">���</a>.</p><p>��� �� �������� ���������, ����� �� ����� �� ��� <a href="mailto:%s">�����������</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => '� �������� `<b>%s</b>\' ��� ����� ��������� (<b>%s</b>).'\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-
-/**
- * @file languages/japanese.php
- * @author fnorif (fnorif@yahoo.co.jp)
- *
- * Now Encoding is EUC-JP and LF
- **/
-
-$this->_strings = array(
- CAS_STR_USING_SERVER
- => 'using server',
- CAS_STR_AUTHENTICATION_WANTED
- => 'CAS�ˤ��ǧ�ڤ�Ԥ��ޤ�',
- CAS_STR_LOGOUT
- => 'CAS����?�����Ȥ��ޤ�!',
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED
- => 'CAS�����Ф˹Ԥ�ɬ�פ�����ޤ�����ưŪ��ž������ʤ����� <a href="%s">������</a> ��å�����³�Ԥ��ޤ���',
- CAS_STR_AUTHENTICATION_FAILED
- => 'CAS�ˤ��ǧ�ڤ˼��Ԥ��ޤ���',
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED
- => '<p>ǧ�ڤǤ��ޤ���Ǥ���.</p><p>�⤦���٥ꥯ�����Ȥ������������<a href="%s">������</a>��å�.</p><p>���꤬��褷�ʤ����� <a href="mailto:%s">���Υ����Ȥδ����</a>���䤤��碌�Ƥ�������.</p>',
- CAS_STR_SERVICE_UNAVAILABLE
- => '�����ӥ� `<b>%s</b>\' �����ѤǤ��ޤ��� (<b>%s</b>).'
-);
-
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/languages.php\r
- * Internationalization constants\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-//@{\r
-/**\r
- * a phpCAS string index\r
- */\r
-define("CAS_STR_USING_SERVER", 1);\r
-define("CAS_STR_AUTHENTICATION_WANTED", 2);\r
-define("CAS_STR_LOGOUT", 3);\r
-define("CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED", 4);\r
-define("CAS_STR_AUTHENTICATION_FAILED", 5);\r
-define("CAS_STR_YOU_WERE_NOT_AUTHENTICATED", 6);\r
-define("CAS_STR_SERVICE_UNAVAILABLE", 7);\r
-//@}\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/spanish.php\r
- * @author Iván-Benjamín García Torà <ivaniclixx AT gmail DOT com>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'usando servidor',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => '¡Autentificación CAS necesaria!',\r
- CAS_STR_LOGOUT \r
- => '¡Salida CAS necesaria!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'Ya debería haber sido redireccionado al servidor CAS. Haga click <a href="%s">aquí</a> para continuar.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => '¡Autentificación CAS fallida!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>No estás autentificado.</p><p>Puedes volver a intentarlo haciendo click <a href="%s">aquí</a>.</p><p>Si el problema persiste debería contactar con el <a href="mailto:%s">administrador de este sitio</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'El servicio `<b>%s</b>\' no está disponible (<b>%s</b>).'\r
-);\r
-\r
-?>\r
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-use SimpleXMLElement;
-
-/** XMPPHP_XMLStream */
-require_once __DIR__ . "/XMPP.php";
-
-/**
- * XMPPHP BOSH
- *
- * @property int lat
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class BOSH extends XMPP
-{
- /**
- * @var integer
- */
- protected $rid;
-
- /**
- * @var string
- */
- protected $sid;
-
- /**
- * @var string
- */
- protected $http_server;
-
- /**
- * @var array
- */
- protected $http_buffer = array();
-
- /**
- * @var string
- */
- protected $session = false;
-
- /**
- * @var integer
- */
- protected $inactivity;
-
- /**
- * Connect
- *
- * @param $server
- * @param $wait
- * @param $session
- * @throws Exception
- * @throws Exception
- */
- public function connect($server = null, $wait = '1', $session = false)
- {
-
- if (is_null($server)) {
-
- // If we aren't given the server http url, try and guess it
- $port_string = ($this->port AND $this->port != 80) ? ':' . $this->port : '';
- $this->http_server = 'http://' . $this->host . $port_string . '/http-bind/';
- } else {
- $this->http_server = $server;
- }
-
- $this->use_encryption = false;
- $this->session = $session;
- $this->rid = 3001;
- $this->sid = null;
- $this->inactivity = 0;
-
- if ($session) {
- $this->loadSession();
- }
-
- if (!$this->sid) {
-
- $body = $this->__buildBody();
- $body->addAttribute('hold', '1');
- $body->addAttribute('to', $this->server);
- $body->addAttribute('route', 'xmpp:' . $this->host . ':' . $this->port);
- $body->addAttribute('secure', 'true');
- $body->addAttribute('xmpp:version', '1.0', 'urn:xmpp:xbosh');
- $body->addAttribute('wait', strval($wait));
- $body->addAttribute('ack', '1');
- $body->addAttribute('xmlns:xmpp', 'urn:xmpp:xbosh');
- $buff = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">';
- xml_parse($this->parser, $buff, false);
- $response = $this->__sendBody($body);
- $rxml = new SimpleXMLElement($response);
- $this->sid = $rxml['sid'];
- $this->inactivity = $rxml['inactivity'];
- } else {
- $buff = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">';
- xml_parse($this->parser, $buff, false);
- }
- }
-
- /**
- * Load session
- *
- */
- public function loadSession()
- {
-
- if ($this->session == 'ON_FILE') {
-
- // Session not started so use session_file
- $session_file = $this->getSessionFile();
-
- // manage multiple accesses
- if (!file_exists($session_file)) {
- file_put_contents($session_file, '');
- }
- $session_file_fp = fopen($session_file, 'r');
- flock($session_file_fp, LOCK_EX);
- $session_serialized = file_get_contents($session_file, null, null, 6);
- flock($session_file_fp, LOCK_UN);
- fclose($session_file_fp);
-
- $this->log->log('SESSION: reading ' . $session_serialized . ' from ' . $session_file, Log::LEVEL_VERBOSE);
- if ($session_serialized != '') {
- $_SESSION['XMPPHP_BOSH'] = unserialize($session_serialized);
- }
- }
-
- if (isset($_SESSION['XMPPHP_BOSH']['inactivity'])) {
- $this->inactivity = $_SESSION['XMPPHP_BOSH']['inactivity'];
- }
-
- $this->lat = (time() - (isset($_SESSION['XMPPHP_BOSH']['lat']))) ? $_SESSION['XMPPHP_BOSH']['lat'] : 0;
-
- if ($this->lat < $this->inactivity) {
-
- if (isset($_SESSION['XMPPHP_BOSH']['RID'])) {
- $this->rid = $_SESSION['XMPPHP_BOSH']['RID'];
- }
- if (isset($_SESSION['XMPPHP_BOSH']['SID'])) {
- $this->sid = $_SESSION['XMPPHP_BOSH']['SID'];
- }
- if (isset($_SESSION['XMPPHP_BOSH']['authed'])) {
- $this->authed = $_SESSION['XMPPHP_BOSH']['authed'];
- }
- if (isset($_SESSION['XMPPHP_BOSH']['basejid'])) {
- $this->basejid = $_SESSION['XMPPHP_BOSH']['basejid'];
- }
- if (isset($_SESSION['XMPPHP_BOSH']['fulljid'])) {
- $this->fulljid = $_SESSION['XMPPHP_BOSH']['fulljid'];
- }
- }
- }
-
- /**
- * Get the session file
- *
- */
- public function getSessionFile()
- {
- return sys_get_temp_dir() . '/' . $this->user . '_' . $this->server . '_session';
- }
-
- /**
- * Build body
- *
- * @param $sub
- * @return SimpleXMLElement|string
- */
- public function __buildBody($sub = null)
- {
-
- $xml = '<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" />';
- $xml = new SimpleXMLElement($xml);
- $xml->addAttribute('content', 'text/xml; charset=utf-8');
- $xml->addAttribute('rid', $this->rid);
- $this->rid++;
- if ($this->sid) {
- $xml->addAttribute('sid', $this->sid);
- }
-
- $xml->addAttribute('xml:lang', 'en');
-
- if ($sub !== null) {
-
- // Ok, so simplexml is lame
- $parent = dom_import_simplexml($xml);
- $content = dom_import_simplexml($sub);
- $child = $parent->ownerDocument->importNode($content, true);
- $parent->appendChild($child);
- $xml = simplexml_import_dom($parent);
- }
-
- return $xml;
- }
-
- /**
- * Send body
- *
- * @param $body
- * @param $recv
- * @return bool|string
- * @throws Exception
- * @throws Exception
- */
- public function __sendBody($body = null, $recv = true)
- {
-
- if (!$body) {
- $body = $this->__buildBody();
- }
-
- $output = '';
- $header = array('Accept-Encoding: gzip, deflate', 'Content-Type: text/xml; charset=utf-8');
- $ch = curl_init();
-
- curl_setopt($ch, CURLOPT_URL, $this->http_server);
- curl_setopt($ch, CURLOPT_HEADER, 0);
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $body->asXML());
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
- curl_setopt($ch, CURLOPT_VERBOSE, 0);
-
- if ($recv) {
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- $output = curl_exec($ch);
- if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != '200') {
- throw new Exception('Wrong response from server!');
- }
-
- $this->http_buffer[] = $output;
- }
- curl_close($ch);
-
- return $output;
- }
-
- /**
- * Process
- *
- * @param $null1
- * @param $null2
- *
- * null params are not used and just to statify Strict Function Declaration
- * @return bool
- * @throws Exception
- * @throws Exception
- */
- public function __process($null1 = null, $null2 = null)
- {
-
- if ($this->http_buffer) {
- $this->__parseBuffer();
- } else {
- $this->__sendBody();
- $this->__parseBuffer();
- }
-
- $this->saveSession();
-
- return true;
- }
-
- public function __parseBuffer()
- {
-
- while ($this->http_buffer) {
-
- $idx = key($this->http_buffer);
- $buffer = $this->http_buffer[$idx];
- unset($this->http_buffer[$idx]);
-
- if ($buffer) {
-
- $xml = new SimpleXMLElement($buffer);
- $children = $xml->xpath('child::node()');
-
- foreach ($children as $child) {
- $buff = $child->asXML();
- $this->log->log('RECV: ' . $buff, Log::LEVEL_VERBOSE);
- xml_parse($this->parser, $buff, false);
- }
- }
- }
- }
-
- /**
- * Save session
- *
- */
- public function saveSession()
- {
-
- $_SESSION['XMPPHP_BOSH']['RID'] = (string)$this->rid;
- $_SESSION['XMPPHP_BOSH']['SID'] = (string)$this->sid;
- $_SESSION['XMPPHP_BOSH']['authed'] = (boolean)$this->authed;
- $_SESSION['XMPPHP_BOSH']['basejid'] = (string)$this->basejid;
- $_SESSION['XMPPHP_BOSH']['fulljid'] = (string)$this->fulljid;
- $_SESSION['XMPPHP_BOSH']['inactivity'] = (string)$this->inactivity;
- $_SESSION['XMPPHP_BOSH']['lat'] = (string)time();
-
- if ($this->session == 'ON_FILE') {
-
- $session_file = $this->getSessionFile();
- $session_file_fp = fopen($session_file, 'r');
- flock($session_file_fp, LOCK_EX);
- // <?php prefix used to mask the content of the session file
- $session_serialized = '<?php ' . serialize($_SESSION);
- file_put_contents($session_file, $session_serialized);
- flock($session_file_fp, LOCK_UN);
- fclose($session_file_fp);
- }
- }
-
- /**
- * Process
- *
- * @param $msg
- * @param $null
- *
- * null param are not used and just to statify Strict Function Declaration
- * @throws Exception
- * @throws Exception
- */
- public function send($msg, $null = null)
- {
- $this->log->log('SEND: ' . $msg, Log::LEVEL_VERBOSE);
- $msg = new SimpleXMLElement($msg);
- $this->__sendBody($this->__buildBody($msg), true);
- }
-
- /**
- * Reset
- *
- * @throws Exception
- */
- public function reset()
- {
-
- $this->xml_depth = 0;
- unset($this->xmlobj);
- $this->xmlobj = array();
- $this->setupParser();
- $body = $this->__buildBody();
- $body->addAttribute('to', $this->host);
- $body->addAttribute('xmpp:restart', 'true', 'urn:xmpp:xbosh');
- $buff = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">';
- $response = $this->__sendBody($body);
- $this->been_reset = true;
- xml_parse($this->parser, $buff, false);
- }
-
- /**
- * Disconnect
- *
- * @throws Exception
- */
- public function disconnect()
- {
-
- parent::disconnect();
-
- if ($this->session == 'ON_FILE') {
- unlink($this->getSessionFile());
- } else {
- $keys = array('RID', 'SID', 'authed', 'basejid', 'fulljid', 'inactivity', 'lat');
- foreach ($keys as $key) {
- unset($_SESSION['XMPPHP_BOSH'][$key]);
- }
- }
- }
-}
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-use Exception as ObjectException;
-
-/**
- * XMPPHP Exception
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class Exception extends ObjectException
-{
-}
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-/**
- * XMPPHP Log
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class Log
-{
- const LEVEL_ERROR = 0;
- const LEVEL_WARNING = 1;
- const LEVEL_INFO = 2;
- const LEVEL_DEBUG = 3;
- const LEVEL_VERBOSE = 4;
-
- /**
- * @var array
- */
- protected $data = array();
-
- /**
- * @var array
- */
- protected $names = array('ERROR', 'WARNING', 'INFO', 'DEBUG', 'VERBOSE');
-
- /**
- * @var integer
- */
- protected $runlevel;
-
- /**
- * @var boolean
- */
- protected $printout;
-
- /**
- * Constructor
- *
- * @param boolean $printout
- * @param int $runlevel
- */
- public function __construct($printout = false, $runlevel = self::LEVEL_INFO)
- {
- $this->printout = (boolean)$printout;
- $this->runlevel = (int)$runlevel;
- }
-
- /**
- * Add a message to the log data array
- * If printout in this instance is set to true, directly output the message
- *
- * @param string $msg
- * @param integer $runlevel
- */
- public function log($msg, $runlevel = self::LEVEL_INFO)
- {
- $time = time();
- #$this->data[] = array($this->runlevel, $msg, $time);
- if ($this->printout and $runlevel <= $this->runlevel) {
- $this->writeLine($msg, $runlevel, $time);
- }
- }
-
- protected function writeLine($msg, $runlevel, $time)
- {
- //echo date('Y-m-d H:i:s', $time)." [".$this->names[$runlevel]."]: ".$msg."\n";
- echo $time . " [" . $this->names[$runlevel] . "]: " . $msg . "\n";
- flush();
- }
-
- /**
- * Output the complete log.
- * Log will be cleared if $clear = true
- *
- * @param boolean $clear
- * @param integer $runlevel
- */
- public function printout($clear = true, $runlevel = null)
- {
- if ($runlevel === null) {
- $runlevel = $this->runlevel;
- }
- foreach ($this->data as $data) {
- if ($runlevel <= $data[0]) {
- $this->writeLine($data[1], $runlevel, $data[2]);
- }
- }
- if ($clear) {
- $this->data = array();
- }
- }
-}
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-/**
- * XMPPHP Roster
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class Roster
-{
- /**
- * Roster array, handles contacts and presence. Indexed by jid.
- * Contains array with potentially two indexes 'contact' and 'presence'
- * @var array
- */
- protected $roster_array = array();
-
- /**
- * Constructor
- * @param array $roster_array
- */
- public function __construct($roster_array = array())
- {
- if ($this->verifyRoster($roster_array)) {
- $this->roster_array = $roster_array; //Allow for pre-population with existing roster
- } else {
- $this->roster_array = array();
- }
- }
-
- /**
- *
- * Check that a given roster array is of a valid structure (empty is still valid)
- *
- * @param array $roster_array
- * @return bool
- */
- protected function verifyRoster($roster_array)
- {
- #TODO once we know *what* a valid roster array looks like
- return true;
- }
-
- /**
- *
- * Retrieve contact via jid
- *
- * @param string $jid
- * @return mixed
- */
- public function getContact($jid)
- {
- if ($this->isContact($jid)) {
- return $this->roster_array[$jid]['contact'];
- }
- }
-
- /**
- *
- * Discover if a contact exists in the roster via jid
- *
- * @param string $jid
- * @return bool
- */
- public function isContact($jid)
- {
- return (array_key_exists($jid, $this->roster_array));
- }
-
- /**
- *
- * Set presence
- *
- * @param string $presence
- * @param integer $priority
- * @param string $show
- * @param string $status
- */
- public function setPresence($presence, $priority, $show, $status)
- {
- $presence = explode('/', $presence, 2);
- $jid = $presence[0];
- $resource = isset($presence[1]) ? $presence[1] : '';
- if ($show != 'unavailable') {
- if (!$this->isContact($jid)) {
- $this->addContact($jid, 'not-in-roster');
- }
- $this->roster_array[$jid]['presence'][$resource] = array('priority' => $priority, 'show' => $show, 'status' => $status);
- } else { //Nuke unavailable resources to save memory
- unset($this->roster_array[$jid]['resource'][$resource]);
- unset($this->roster_array[$jid]['presence'][$resource]);
- }
- }
-
- /**
- *
- * Add given contact to roster
- *
- * @param string $jid
- * @param string $subscription
- * @param string $name
- * @param array $groups
- */
- public function addContact($jid, $subscription, $name = '', $groups = array())
- {
- $contact = array('jid' => $jid, 'subscription' => $subscription, 'name' => $name, 'groups' => $groups);
- if ($this->isContact($jid)) {
- $this->roster_array[$jid]['contact'] = $contact;
- } else {
- $this->roster_array[$jid] = array('contact' => $contact);
- }
- }
-
- /*
- *
- * Return best presence for jid
- *
- * @param string $jid
- */
-
- public function getPresence($jid)
- {
- $split = explode('/', $jid, 2);
- $jid = $split[0];
- if ($this->isContact($jid)) {
- $current = array('resource' => '', 'active' => '', 'priority' => -129, 'show' => '', 'status' => ''); //Priorities can only be -128 = 127
- foreach ($this->roster_array[$jid]['presence'] as $resource => $presence) {
- //Highest available priority or just highest priority
- if ($presence['priority'] > $current['priority'] and (($presence['show'] == "chat" or $presence['show'] == "available") or ($current['show'] != "chat" or $current['show'] != "available"))) {
- $current = $presence;
- $current['resource'] = $resource;
- }
- }
- return $current;
- }
- }
-
- /**
- *
- * Get roster
- *
- */
- public function getRoster()
- {
- return $this->roster_array;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-/**
- * XMPPHP XMLObject
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class XMLObj
-{
- /**
- * Tag name
- *
- * @var string
- */
- public $name;
-
- /**
- * Namespace
- *
- * @var string
- */
- public $ns;
-
- /**
- * Attributes
- *
- * @var array
- */
- public $attrs = array();
-
- /**
- * Subs?
- *
- * @var array
- */
- public $subs = array();
-
- /**
- * Node data
- *
- * @var string
- */
- public $data = '';
-
- /**
- * Constructor
- *
- * @param string $name
- * @param string $ns
- * @param array $attrs
- * @param string $data
- */
- public function __construct($name, $ns = '', $attrs = array(), $data = '')
- {
- $this->name = strtolower($name);
- $this->ns = $ns;
- if (is_array($attrs) && count($attrs)) {
- foreach ($attrs as $key => $value) {
- $this->attrs[strtolower($key)] = $value;
- }
- }
- $this->data = $data;
- }
-
- /**
- * Dump this XML Object to output.
- *
- * @param integer $depth
- */
- public function printObj($depth = 0)
- {
- print str_repeat("\t", $depth) . $this->name . " " . $this->ns . ' ' . $this->data;
- print "\n";
- foreach ($this->subs as $sub) {
- $sub->printObj($depth + 1);
- }
- }
-
- /**
- * Return this XML Object in xml notation
- *
- * @param string $str
- * @return string
- */
- public function toString($str = '')
- {
- $str .= "<{$this->name} xmlns='{$this->ns}' ";
- foreach ($this->attrs as $key => $value) {
- if ($key != 'xmlns') {
- $value = htmlspecialchars($value);
- $str .= "$key='$value' ";
- }
- }
- $str .= ">";
- foreach ($this->subs as $sub) {
- $str .= $sub->toString();
- }
- $body = htmlspecialchars($this->data);
- $str .= "$body</{$this->name}>";
- return $str;
- }
-
- /**
- * Has this XML Object the given sub?
- *
- * @param string $name
- * @param null $ns
- * @return boolean
- */
- public function hasSub($name, $ns = null)
- {
- foreach ($this->subs as $sub) {
- if (($name == "*" or $sub->name == $name) and ($ns == null or $sub->ns == $ns)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Return a sub
- *
- * @param string $name
- * @param string $attrs
- * @param string $ns
- * @return mixed
- */
- public function sub($name, $attrs = null, $ns = null)
- {
- #TODO attrs is ignored
- foreach ($this->subs as $sub) {
- if ($sub->name == $name and ($ns == null or $sub->ns == $ns)) {
- return $sub;
- }
- }
- }
-}
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-/** Exception */
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'Exception.php';
-
-/** XMLObj */
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'XMLObj.php';
-
-/** Log */
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'Log.php';
-
-
-/**
- * XMPPHP XMLStream
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class XMLStream
-{
- /**
- * @var resource
- */
- protected $socket;
- /**
- * @var resource
- */
- protected $parser;
- /**
- * @var string
- */
- protected $buffer;
- /**
- * @var integer
- */
- protected $xml_depth = 0;
- /**
- * @var string
- */
- protected $host;
- /**
- * @var integer
- */
- protected $port;
- /**
- * @var string
- */
- protected $stream_start = '<stream>';
- /**
- * @var string
- */
- protected $stream_end = '</stream>';
- /**
- * @var boolean
- */
- protected $disconnected = false;
- /**
- * @var boolean
- */
- protected $sent_disconnect = false;
- /**
- * @var array
- */
- protected $ns_map = array();
- /**
- * @var array
- */
- protected $current_ns = array();
- /**
- * @var array
- */
- protected $xmlobj = null;
- /**
- * @var array
- */
- protected $nshandlers = array();
- /**
- * @var array
- */
- protected $xpathhandlers = array();
- /**
- * @var array
- */
- protected $idhandlers = array();
- /**
- * @var array
- */
- protected $eventhandlers = array();
- /**
- * @var integer
- */
- protected $lastid = 0;
- /**
- * @var string
- */
- protected $default_ns;
- /**
- * @var string[]
- */
- protected $until = [];
- /**
- * @var int[]
- */
- protected $until_count = [];
- /**
- * @var array
- */
- protected $until_happened = false;
- /**
- * @var array
- */
- protected $until_payload = array();
- /**
- * @var Log
- */
- protected $log;
- /**
- * @var boolean
- */
- protected $reconnect = true;
- /**
- * @var boolean
- */
- protected $been_reset = false;
- /**
- * @var boolean
- */
- protected $is_server;
- /**
- * @var float
- */
- protected $last_send = 0;
- /**
- * @var boolean
- */
- protected $use_ssl = false;
- /**
- * @var integer
- */
- protected $reconnectTimeout = 30;
-
- /**
- * Constructor
- *
- * @param string $host
- * @param string $port
- * @param boolean $printlog
- * @param string $loglevel
- * @param boolean $is_server
- */
- public function __construct($host = null, $port = null, $printlog = false, $loglevel = null, $is_server = false)
- {
- $this->reconnect = !$is_server;
- $this->is_server = $is_server;
- $this->host = $host;
- $this->port = $port;
- $this->setupParser();
- $this->log = new Log($printlog, $loglevel);
- }
-
- /**
- * Setup the XML parser
- */
- public function setupParser()
- {
- $this->parser = xml_parser_create('UTF-8');
- xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
- xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
- xml_set_object($this->parser, $this);
- xml_set_element_handler($this->parser, 'startXML', 'endXML');
- xml_set_character_data_handler($this->parser, 'charXML');
- }
-
- /**
- * Destructor
- * Cleanup connection
- */
- public function __destruct()
- {
- if (!$this->disconnected && $this->socket) {
- $this->disconnect();
- }
- }
-
- /**
- * Disconnect from XMPP Host
- */
- public function disconnect()
- {
- $this->log->log("Disconnecting...", Log::LEVEL_VERBOSE);
- if (false == (bool)$this->socket) {
- return;
- }
- $this->reconnect = false;
- $this->send($this->stream_end);
- $this->sent_disconnect = true;
- $this->processUntil('end_stream', 5);
- $this->disconnected = true;
- }
-
- /**
- * Send to socket
- *
- * @param string $msg
- * @param null $timeout
- * @return bool|int
- * @throws Exception
- */
- public function send($msg, $timeout = NULL)
- {
-
- if (is_null($timeout)) {
- $secs = NULL;
- $usecs = NULL;
- } else if ($timeout == 0) {
- $secs = 0;
- $usecs = 0;
- } else {
- $maximum = $timeout * 1000000;
- $usecs = $maximum % 1000000;
- $secs = floor(($maximum - $usecs) / 1000000);
- }
-
- $read = array();
- $write = array($this->socket);
- $except = array();
-
- $select = @stream_select($read, $write, $except, $secs, $usecs);
-
- if ($select === False) {
- $this->log->log("ERROR sending message; reconnecting.");
- $this->doReconnect();
- # TODO: retry send here
- return false;
- } elseif ($select > 0) {
- $this->log->log("Socket is ready; send it.", Log::LEVEL_VERBOSE);
- } else {
- $this->log->log("Socket is not ready; break.", Log::LEVEL_ERROR);
- return false;
- }
-
- $sentbytes = @fwrite($this->socket, $msg);
- $this->log->log("SENT: " . mb_substr($msg, 0, $sentbytes, '8bit'), Log::LEVEL_VERBOSE);
- if ($sentbytes === FALSE) {
- $this->log->log("ERROR sending message; reconnecting.", Log::LEVEL_ERROR);
- $this->doReconnect();
- return false;
- }
- $this->log->log("Successfully sent $sentbytes bytes.", Log::LEVEL_VERBOSE);
- return $sentbytes;
- }
-
- /**
- * Reconnect XMPP Host
- * @throws Exception
- */
- public function doReconnect()
- {
- if (!$this->is_server) {
- $this->log->log("Reconnecting ($this->reconnectTimeout)...", Log::LEVEL_WARNING);
- $this->connect($this->reconnectTimeout, false, false);
- $this->reset();
- $this->event('reconnect');
- }
- }
-
- /**
- * Connect to XMPP Host
- *
- * @param integer $timeout
- * @param boolean $persistent
- * @param boolean $sendinit
- * @throws Exception
- * @throws Exception
- */
- public function connect($timeout = 30, $persistent = false, $sendinit = true)
- {
- $this->sent_disconnect = false;
- $starttime = time();
-
- do {
- $this->disconnected = false;
- $this->sent_disconnect = false;
- if ($persistent) {
- $conflag = STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT;
- } else {
- $conflag = STREAM_CLIENT_CONNECT;
- }
- $conntype = 'tcp';
- if ($this->use_ssl) $conntype = 'ssl';
- $this->log->log("Connecting to $conntype://{$this->host}:{$this->port}");
- $this->socket = @stream_socket_client("$conntype://{$this->host}:{$this->port}", $errno, $errstr, $timeout, $conflag);
- if (!$this->socket) {
- $this->log->log("Could not connect.", Log::LEVEL_ERROR);
- $this->disconnected = true;
- # Take it easy for a few seconds
- sleep(min($timeout, 5));
- }
- } while (!$this->socket && (time() - $starttime) < $timeout);
-
- if ($this->socket) {
- stream_set_blocking($this->socket, 1);
- if ($sendinit) $this->send($this->stream_start);
- } else {
- throw new Exception("Could not connect before timeout.");
- }
- }
-
- /**
- * Reset connection
- */
- public function reset()
- {
- $this->xml_depth = 0;
- unset($this->xmlobj);
- $this->xmlobj = array();
- $this->setupParser();
- if (!$this->is_server) {
- $this->send($this->stream_start);
- }
- $this->been_reset = true;
- }
-
- /**
- * Event?
- *
- * @param string $name
- * @param string $payload
- */
- public function event($name, $payload = null)
- {
- $this->log->log("EVENT: $name", Log::LEVEL_DEBUG);
- foreach ($this->eventhandlers as $handler) {
- if ($name == $handler[0]) {
- if ($handler[2] === null) {
- $handler[2] = $this;
- }
- $handler[2]->{$handler[1]}($payload);
- }
- }
- foreach ($this->until as $key => $until) {
- if (is_array($until)) {
- if (in_array($name, $until)) {
- $this->until_payload[$key][] = array($name, $payload);
- if (!isset($this->until_count[$key])) {
- $this->until_count[$key] = 0;
- }
- $this->until_count[$key] += 1;
- #$this->until[$key] = false;
- }
- }
- }
- }
-
- /**
- * Process until a specified event or a timeout occurs
- *
- * @param string|array $event
- * @param integer $timeout
- * @return string
- * @throws Exception
- */
- public function processUntil($event, $timeout = -1)
- {
- $start = time();
- if (!is_array($event)) $event = array($event);
- $this->until[] = $event;
- end($this->until);
- $event_key = key($this->until);
- reset($this->until);
- $this->until_count[$event_key] = 0;
- while (!$this->disconnected and $this->until_count[$event_key] < 1 and (time() - $start < $timeout or $timeout == -1)) {
- $this->__process();
- }
- if (array_key_exists($event_key, $this->until_payload)) {
- $payload = $this->until_payload[$event_key];
- unset($this->until_payload[$event_key]);
- unset($this->until_count[$event_key]);
- unset($this->until[$event_key]);
- } else {
- $payload = array();
- }
- return $payload;
- }
-
- /**
- * Core reading tool
- * 0 -> only read if data is immediately ready
- * NULL -> wait forever and ever
- * integer -> process for this amount of time
- * @param int $maximum
- * @return bool
- * @throws Exception
- */
-
- private function __process($maximum = 5)
- {
-
- $remaining = $maximum;
-
- do {
- $starttime = (microtime(true) * 1000000);
- $read = array($this->socket);
- $write = array();
- $except = array();
- if (is_null($maximum)) {
- $secs = NULL;
- $usecs = NULL;
- } else if ($maximum == 0) {
- $secs = 0;
- $usecs = 0;
- } else {
- $usecs = $remaining % 1000000;
- $secs = floor(($remaining - $usecs) / 1000000);
- }
- $updated = @stream_select($read, $write, $except, $secs, $usecs);
- if ($updated === false) {
- $this->log->log("Error on stream_select()", Log::LEVEL_VERBOSE);
- if ($this->reconnect) {
- $this->doReconnect();
- } else {
- fclose($this->socket);
- $this->socket = NULL;
- return false;
- }
- } else if ($updated > 0) {
- # XXX: Is this big enough?
- $buff = @fread($this->socket, 4096);
- if (!$buff) {
- if ($this->reconnect) {
- $this->doReconnect();
- } else {
- fclose($this->socket);
- $this->socket = NULL;
- return false;
- }
- }
- $this->log->log("RECV: $buff", Log::LEVEL_VERBOSE);
- xml_parse($this->parser, $buff, false);
- } // Otherwise,
- // $updated == 0 means no changes during timeout.
-
- $endtime = (microtime(true) * 1000000);
- $time_past = $endtime - $starttime;
- $remaining = $remaining - $time_past;
- } while (is_null($maximum) || $remaining > 0);
- return true;
- }
-
- /**
- * Return the log instance
- *
- * @return Log
- */
- public function getLog()
- {
- return $this->log;
- }
-
- /**
- * Get next ID
- *
- * @return integer
- */
- public function getId()
- {
- $this->lastid++;
- return $this->lastid;
- }
-
- /**
- * Set SSL
- * @param bool $use
- */
- public function useSSL($use = true)
- {
- $this->use_ssl = $use;
- }
-
- /**
- * Add ID Handler
- *
- * @param integer $id
- * @param string $pointer
- * @param string $obj
- */
- public function addIdHandler($id, $pointer, $obj = null)
- {
- $this->idhandlers[$id] = array($pointer, $obj);
- }
-
- /**
- * Add Handler
- *
- * @param string $name
- * @param string $ns
- * @param string $pointer
- * @param string $obj
- * @param integer $depth
- */
- public function addHandler($name, $ns, $pointer, $obj = null, $depth = 1)
- {
- #TODO deprication warning
- $this->nshandlers[] = array($name, $ns, $pointer, $obj, $depth);
- }
-
- /**
- * Add XPath Handler
- *
- * @param string $xpath
- * @param string $pointer
- * @param
- */
- public function addXPathHandler($xpath, $pointer, $obj = null)
- {
- if (preg_match_all("/\(?{[^\}]+}\)?(\/?)[^\/]+/", $xpath, $regs)) {
- $ns_tags = $regs[0];
- } else {
- $ns_tags = array($xpath);
- }
- foreach ($ns_tags as $ns_tag) {
- list($l, $r) = explode("}", $ns_tag);
- if ($r != null) {
- $xpart = array(substr($l, 1), $r);
- } else {
- $xpart = array(null, $l);
- }
- $xpath_array[] = $xpart;
- }
- $this->xpathhandlers[] = array($xpath_array, $pointer, $obj);
- }
-
- /**
- * Add Event Handler
- *
- * @param $name
- * @param string $pointer
- * @param string $obj
- */
- public function addEventHandler($name, $pointer, $obj)
- {
- $this->eventhandlers[] = array($name, $pointer, $obj);
- }
-
- public function setReconnectTimeout($timeout)
- {
- $this->reconnectTimeout = $timeout;
- }
-
- /**
- * Are we are disconnected?
- *
- * @return boolean
- */
- public function isDisconnected()
- {
- return $this->disconnected;
- }
-
- /**
- * Process
- *
- */
- public function process()
- {
- $this->__process(NULL);
- }
-
- /**
- * Process until a timeout occurs
- *
- * @param integer $timeout
- * @return string
- * @throws Exception
- */
- public function processTime($timeout = NULL)
- {
- if (is_null($timeout)) {
- return $this->__process(NULL);
- } else {
- return $this->__process($timeout * 1000000);
- }
- }
-
- /**
- * Obsolete?
- * @param $socket
- */
- public function Xapply_socket($socket)
- {
- $this->socket = $socket;
- }
-
- /**
- * XML start callback
- *
- * @param resource $parser
- * @param string $name
- * @param $attr
- * @see xml_set_element_handler
- */
- public function startXML($parser, $name, $attr)
- {
- if ($this->been_reset) {
- $this->been_reset = false;
- $this->xml_depth = 0;
- }
- $this->xml_depth++;
- if (array_key_exists('XMLNS', $attr)) {
- $this->current_ns[$this->xml_depth] = $attr['XMLNS'];
- } else {
- $this->current_ns[$this->xml_depth] = $this->current_ns[$this->xml_depth - 1];
- if (!$this->current_ns[$this->xml_depth]) $this->current_ns[$this->xml_depth] = $this->default_ns;
- }
- $ns = $this->current_ns[$this->xml_depth];
- foreach ($attr as $key => $value) {
- if (strstr($key, ":")) {
- $key = explode(':', $key);
- $key = $key[1];
- $this->ns_map[$key] = $value;
- }
- }
- if (!strstr($name, ":") === false) {
- $name = explode(':', $name);
- $ns = $this->ns_map[$name[0]];
- $name = $name[1];
- }
- $obj = new XMLObj($name, $ns, $attr);
- if ($this->xml_depth > 1) {
- $this->xmlobj[$this->xml_depth - 1]->subs[] = $obj;
- }
- $this->xmlobj[$this->xml_depth] = $obj;
- }
-
- /**
- * XML end callback
- *
- * @param resource $parser
- * @param string $name
- * @throws Exception
- * @see xml_set_element_handler
- *
- */
- public function endXML($parser, $name)
- {
- #$this->log->log("Ending $name", Log::LEVEL_DEBUG);
- #print "$name\n";
- if ($this->been_reset) {
- $this->been_reset = false;
- $this->xml_depth = 0;
- }
- $this->xml_depth--;
- if ($this->xml_depth == 1) {
- #clean-up old objects
- #$found = false; #FIXME This didn't appear to be in use --Gar
- foreach ($this->xpathhandlers as $handler) {
- if (is_array($this->xmlobj) && array_key_exists(2, $this->xmlobj)) {
- $searchxml = $this->xmlobj[2];
- $nstag = array_shift($handler[0]);
- if (($nstag[0] == null or $searchxml->ns == $nstag[0]) and ($nstag[1] == "*" or $nstag[1] == $searchxml->name)) {
- foreach ($handler[0] as $nstag) {
- if ($searchxml !== null and $searchxml->hasSub($nstag[1], $ns = $nstag[0])) {
- $searchxml = $searchxml->sub($nstag[1], $ns = $nstag[0]);
- } else {
- $searchxml = null;
- break;
- }
- }
- if ($searchxml !== null) {
- if ($handler[2] === null) $handler[2] = $this;
- $this->log->log("Calling {$handler[1]}", Log::LEVEL_DEBUG);
- $handler[2]->{$handler[1]}($this->xmlobj[2]);
- }
- }
- }
- }
- foreach ($this->nshandlers as $handler) {
- if ($handler[4] != 1 and array_key_exists(2, $this->xmlobj) and $this->xmlobj[2]->hasSub($handler[0])) {
- $searchxml = $this->xmlobj[2]->sub($handler[0]);
- } elseif (is_array($this->xmlobj) and array_key_exists(2, $this->xmlobj)) {
- $searchxml = $this->xmlobj[2];
- }
- if ($searchxml !== null and $searchxml->name == $handler[0] and ($searchxml->ns == $handler[1] or (!$handler[1] and $searchxml->ns == $this->default_ns))) {
- if ($handler[3] === null) $handler[3] = $this;
- $this->log->log("Calling {$handler[2]}", Log::LEVEL_DEBUG);
- $handler[3]->{$handler[2]}($this->xmlobj[2]);
- }
- }
- foreach ($this->idhandlers as $id => $handler) {
- if (array_key_exists('id', $this->xmlobj[2]->attrs) and $this->xmlobj[2]->attrs['id'] == $id) {
- if ($handler[1] === null) $handler[1] = $this;
- $handler[1]->{$handler[0]}($this->xmlobj[2]);
- #id handlers are only used once
- unset($this->idhandlers[$id]);
- break;
- }
- }
- if (is_array($this->xmlobj)) {
- $this->xmlobj = array_slice($this->xmlobj, 0, 1);
- if (isset($this->xmlobj[0]) && $this->xmlobj[0] instanceof XMLObj) {
- $this->xmlobj[0]->subs = null;
- }
- }
- unset($this->xmlobj[2]);
- }
- if ($this->xml_depth == 0 and !$this->been_reset) {
- if (!$this->disconnected) {
- if (!$this->sent_disconnect) {
- $this->send($this->stream_end);
- }
- $this->disconnected = true;
- $this->sent_disconnect = true;
- fclose($this->socket);
- if ($this->reconnect) {
- $this->doReconnect();
- }
- }
- $this->event('end_stream');
- }
- }
-
- /**
- * XML character callback
- * @param resource $parser
- * @param string $data
- * @see xml_set_character_data_handler
- *
- */
- public function charXML($parser, $data)
- {
- if (array_key_exists($this->xml_depth, $this->xmlobj)) {
- $this->xmlobj[$this->xml_depth]->data .= $data;
- }
- }
-
- /**
- * Read from socket
- */
- public function read()
- {
- $buff = @fread($this->socket, 1024);
- if (!$buff) {
- if ($this->reconnect) {
- $this->doReconnect();
- } else {
- fclose($this->socket);
- return false;
- }
- }
- $this->log->log("RECV: $buff", Log::LEVEL_VERBOSE);
- xml_parse($this->parser, $buff, false);
- }
-
- public function time()
- {
- list($usec, $sec) = explode(" ", microtime());
- return (float)$sec + (float)$usec;
- }
-
- public function readyToProcess()
- {
- $read = array($this->socket);
- $write = array();
- $except = array();
- $updated = @stream_select($read, $write, $except, 0);
- return (($updated !== false) && ($updated > 0));
- }
-}
+++ /dev/null
-<?php
-
-/**
- * XMPPHP: The PHP XMPP Library
- * Copyright (C) 2008 Nathanael C. Fritz
- * This file is part of SleekXMPP.
- *
- * XMPPHP 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.
- *
- * XMPPHP 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 XMPPHP; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category xmpphp
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @author Alexander Birkner (https://github.com/BirknerAlex)
- * @author zorn-v (https://github.com/zorn-v/xmpphp/)
- * @author GNU social
- * @copyright 2008 Nathanael C. Fritz
- */
-
-namespace XMPPHP;
-
-/** XMPPHP_XMLStream */
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'XMLStream.php';
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'Roster.php';
-
-
-/**
- * XMPPHP XMPP
- *
- * @package XMPPHP
- * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
- * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
- * @author Michael Garvin <JID: gar@netflint.net>
- * @copyright 2008 Nathanael C. Fritz
- * @version $Id$
- */
-class XMPP extends XMLStream
-{
- /**
- * @var string
- */
- public $server;
-
- /**
- * @var string
- */
- public $user;
- /**
- * @var boolean
- */
- public $track_presence = true;
- /**
- * @var object
- */
- public $roster;
- /**
- * @var string
- */
- protected $password;
- /**
- * @var string
- */
- protected $resource;
- /**
- * @var string
- */
- protected $fulljid;
- /**
- * @var string
- */
- protected $basejid;
- /**
- * @var boolean
- */
- protected $authed = false;
- protected $session_started = false;
- /**
- * @var boolean
- */
- protected $auto_subscribe = false;
- /**
- * @var boolean
- */
- protected $use_encryption = true;
-
- /**
- * Constructor
- *
- * @param string $host
- * @param integer $port
- * @param string $user
- * @param string $password
- * @param string $resource
- * @param string $server
- * @param boolean $printlog
- * @param string $loglevel
- */
- public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null)
- {
- parent::__construct($host, $port, $printlog, $loglevel);
-
- $this->user = $user;
- $this->password = $password;
- $this->resource = $resource;
- if (!$server) {
- $server = $host;
- }
- $this->server = $server;
- $this->basejid = $this->user . '@' . $this->host;
-
- $this->roster = new Roster();
- $this->track_presence = true;
-
- $this->stream_start = '<stream:stream to="' . $server . '" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0">';
- $this->stream_end = '</stream:stream>';
- $this->default_ns = 'jabber:client';
-
- $this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler');
- $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler');
- $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler');
- $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler');
- $this->addXPathHandler('{jabber:client}message', 'message_handler');
- $this->addXPathHandler('{jabber:client}presence', 'presence_handler');
- $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
- }
-
- /**
- * Turn encryption on/ff
- *
- * @param boolean $useEncryption
- */
- public function useEncryption($useEncryption = true)
- {
- $this->use_encryption = $useEncryption;
- }
-
- /**
- * Turn on auto-authorization of subscription requests.
- *
- * @param boolean $autoSubscribe
- */
- public function autoSubscribe($autoSubscribe = true)
- {
- $this->auto_subscribe = $autoSubscribe;
- }
-
- /**
- * Send XMPP Message
- *
- * @param string $to
- * @param string $body
- * @param string $type
- * @param string $subject
- * @param null $payload
- * @throws Exception
- */
- public function message($to, $body, $type = 'chat', $subject = null, $payload = null)
- {
- if ($this->disconnected) {
- throw new Exception('You need to connect first');
- }
-
- if (empty($type)) {
- $type = 'chat';
- }
-
- $to = htmlspecialchars($to);
- $body = htmlspecialchars($body);
- $subject = htmlspecialchars($subject);
- $subject = ($subject) ? '<subject>' . $subject . '</subject>' : '';
- $payload = ($payload) ? $payload : '';
- $sprintf = '<message from="%s" to="%s" type="%s">%s<body>%s</body>%s</message>';
- $output = sprintf($sprintf, $this->fulljid, $to, $type, $subject, $body, $payload);
- $this->send($output);
- }
-
- /**
- * Set Presence
- *
- * @param string $status
- * @param string $show
- * @param string $to
- * @param string $type
- * @param null $priority
- * @throws Exception
- */
- public function presence($status = null, $show = 'available', $to = null, $type = 'available', $priority = null)
- {
- if ($this->disconnected) {
- throw new Exception('You need to connect first');
- }
-
- if ($type == 'available') {
- $type = '';
- }
- $to = htmlspecialchars($to);
- $status = htmlspecialchars($status);
- if ($show == 'unavailable') {
- $type = 'unavailable';
- }
-
- $out = "<presence";
- if ($to) {
- $out .= " to=\"$to\"";
- }
- if ($type) {
- $out .= " type='$type'";
- }
- if ($show == 'available' and !$status and $priority !== null) {
- $out .= "/>";
- } else {
- $out .= ">";
- if ($show != 'available') {
- $out .= "<show>$show</show>";
- }
- if ($status) {
- $out .= "<status>$status</status>";
- }
- if ($priority !== null) {
- $out .= "<priority>$priority</priority>";
- }
- $out .= "</presence>";
- }
-
- $this->send($out);
- }
-
- /**
- * Send Auth request
- *
- * @param string $jid
- */
- public function subscribe($jid)
- {
- $this->send("<presence type='subscribe' to='{$jid}' from='{$this->fulljid}' />");
- #$this->send("<presence type='subscribed' to='{$jid}' from='{$this->fulljid}' />");
- }
-
- /**
- * Message handler
- *
- * @param string $xml
- */
- public function message_handler($xml)
- {
- if (isset($xml->attrs['type'])) {
- $payload['type'] = $xml->attrs['type'];
- } else {
- $payload['type'] = 'chat';
- }
- $body = $xml->sub('body');
- $payload['from'] = $xml->attrs['from'];
- $payload['body'] = is_object($body) ? $body->data : false; // $xml->sub('body')->data;
- $payload['xml'] = $xml;
- $this->log->log("Message: {$payload['body']}", Log::LEVEL_DEBUG);
- $this->event('message', $payload);
- }
-
- /**
- * Presence handler
- *
- * @param string $xml
- */
- public function presence_handler($xml)
- {
- $payload['type'] = (isset($xml->attrs['type'])) ? $xml->attrs['type'] : 'available';
- $payload['show'] = (isset($xml->sub('show')->data)) ? $xml->sub('show')->data : $payload['type'];
- $payload['from'] = $xml->attrs['from'];
- $payload['status'] = (isset($xml->sub('status')->data)) ? $xml->sub('status')->data : '';
- $payload['priority'] = (isset($xml->sub('priority')->data)) ? intval($xml->sub('priority')->data) : 0;
- $payload['xml'] = $xml;
- if ($this->track_presence) {
- $this->roster->setPresence($payload['from'], $payload['priority'], $payload['show'], $payload['status']);
- }
- $this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}", Log::LEVEL_DEBUG);
- if (array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribe') {
- if ($this->auto_subscribe) {
- $this->send("<presence type='subscribed' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
- $this->send("<presence type='subscribe' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
- }
- $this->event('subscription_requested', $payload);
- } elseif (array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribed') {
- $this->event('subscription_accepted', $payload);
- } else {
- $this->event('presence', $payload);
- }
- }
-
- /**
- * Retrieves the roster
- *
- */
- public function getRoster()
- {
- $id = $this->getID();
- $this->send("<iq xmlns='jabber:client' type='get' id='$id'><query xmlns='jabber:iq:roster' /></iq>");
- }
-
- /**
- * Retrieves the vcard
- * @param null $jid
- */
- public function getVCard($jid = null)
- {
- $id = $this->getID();
- $this->addIdHandler($id, 'vcard_get_handler');
- if ($jid) {
- $this->send("<iq type='get' id='$id' to='$jid'><vCard xmlns='vcard-temp' /></iq>");
- } else {
- $this->send("<iq type='get' id='$id'><vCard xmlns='vcard-temp' /></iq>");
- }
- }
-
- /**
- * Features handler
- *
- * @param string $xml
- */
- protected function features_handler($xml)
- {
- if ($xml->hasSub('starttls') and $this->use_encryption) {
- $this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
- } elseif ($xml->hasSub('bind') and $this->authed) {
- $id = $this->getId();
- $this->addIdHandler($id, 'resource_bind_handler');
- $this->send("<iq xmlns=\"jabber:client\" type=\"set\" id=\"$id\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>{$this->resource}</resource></bind></iq>");
- } else {
- $this->log->log("Attempting Auth...");
- if ($this->password) {
- $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
- } else {
- $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
- }
- }
- }
-
- /**
- * SASL success handler
- *
- * @param string $xml
- */
- protected function sasl_success_handler($xml)
- {
- $this->log->log("Auth success!");
- $this->authed = true;
- $this->reset();
- }
-
- /**
- * SASL feature handler
- *
- * @param string $xml
- * @throws Exception
- */
- protected function sasl_failure_handler($xml)
- {
- $this->log->log("Auth failed!", Log::LEVEL_ERROR);
- $this->disconnect();
-
- throw new Exception('Auth failed!');
- }
-
- /**
- * Resource bind handler
- *
- * @param string $xml
- */
- protected function resource_bind_handler($xml)
- {
- if ($xml->attrs['type'] == 'result') {
- $this->log->log("Bound to " . $xml->sub('bind')->sub('jid')->data);
- $this->fulljid = $xml->sub('bind')->sub('jid')->data;
- $jidarray = explode('/', $this->fulljid);
- $this->jid = $jidarray[0];
- }
- $id = $this->getId();
- $this->addIdHandler($id, 'session_start_handler');
- $this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
- }
-
- /**
- * Roster iq handler
- * Gets all packets matching XPath "iq/{jabber:iq:roster}query'
- *
- * @param string $xml
- */
- protected function roster_iq_handler($xml)
- {
- $status = "result";
- $xmlroster = $xml->sub('query');
- foreach ($xmlroster->subs as $item) {
- $groups = array();
- if ($item->name == 'item') {
- $jid = $item->attrs['jid']; //REQUIRED
- $name = $item->attrs['name']; //MAY
- $subscription = $item->attrs['subscription'];
- foreach ($item->subs as $subitem) {
- if ($subitem->name == 'group') {
- $groups[] = $subitem->data;
- }
- }
- $contacts[] = array($jid, $subscription, $name, $groups); //Store for action if no errors happen
- } else {
- $status = "error";
- }
- }
- if ($status == "result") { //No errors, add contacts
- foreach ($contacts as $contact) {
- $this->roster->addContact($contact[0], $contact[1], $contact[2], $contact[3]);
- }
- }
- if ($xml->attrs['type'] == 'set') {
- $this->send("<iq type=\"reply\" id=\"{$xml->attrs['id']}\" to=\"{$xml->attrs['from']}\" />");
- }
- }
-
- /**
- * Session start handler
- *
- * @param string $xml
- */
- protected function session_start_handler($xml)
- {
- $this->log->log("Session started");
- $this->session_started = true;
- $this->event('session_start');
- }
-
- /**
- * TLS proceed handler
- *
- * @param string $xml
- */
- protected function tls_proceed_handler($xml)
- {
- $this->log->log("Starting TLS encryption");
- stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
- $this->reset();
- }
-
- /**
- * VCard retrieval handler
- *
- * @param XMLObj $xml
- */
- protected function vcard_get_handler($xml)
- {
- $vcard_array = array();
- $vcard = $xml->sub('vcard');
- // go through all of the sub elements and add them to the vcard array
- foreach ($vcard->subs as $sub) {
- if ($sub->subs) {
- $vcard_array[$sub->name] = array();
- foreach ($sub->subs as $sub_child) {
- $vcard_array[$sub->name][$sub_child->name] = $sub_child->data;
- }
- } else {
- $vcard_array[$sub->name] = $sub->data;
- }
- }
- $vcard_array['from'] = $xml->attrs['from'];
- $this->event('vcard', $vcard_array);
- }
-}
--- /dev/null
+/docs/ export-ignore
+/test/ export-ignore
+/utils/ export-ignore
+/.buildpath export-ignore
+/.gitignore export-ignore
+/.project export-ignore
+/.travis.yml export-ignore
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+require_once dirname(__FILE__).'/source/CAS.php';
\ No newline at end of file
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+Copyright 2007-2011, JA-SIG, Inc.
+This project includes software developed by Jasig.
+http://www.jasig.org/
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software except in compliance with the License.
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+===========================================================================
+
+Copyright © 2003-2007, The ESUP-Portail consortium
+
+Requirements for sources originally licensed under the New BSD License:
+
+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.
+
+- Neither the name of JA-SIG, Inc. nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
+
+===========================================================================
+
+Copyright (c) 2009, Regents of the University of Nebraska
+All rights reserved.
+
+Requirements for CAS_Autloader originally licensed under the New BSD License:
+
+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.
+
+Neither the name of the University of Nebraska nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
--- /dev/null
+phpCAS
+=======
+
+phpCAS is an authentication library that allows PHP applications to easily authenticate
+users via a Central Authentication Service (CAS) server.
+
+Please see the wiki website for more information:
+
+https://wiki.jasig.org/display/CASC/phpCAS
+
+Api documentation can be found here:
+
+https://apereo.github.io/phpCAS/
+
+
+[](https://travis-ci.org/apereo/phpCAS)
+
+
+LICENSE
+-------
+
+Copyright 2007-2015, JA-SIG, Inc.
+This project includes software developed by Jasig.
+http://www.jasig.org/
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software except in compliance with the License.
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null
+{
+ "name": "apereo/phpcas",
+ "description": "Provides a simple API for authenticating users against a CAS server",
+ "keywords": ["cas", "jasig", "apereo"],
+ "homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
+ "type": "library",
+ "license": "Apache-2.0",
+ "authors": [
+ {"name": "Joachim Fritschi", "homepage": "https://wiki.jasig.org/display/~fritschi"},
+ {"name": "Adam Franco", "homepage": "https://wiki.jasig.org/display/~adamfranco"}
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "ext-curl": "*"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~3.7.10"
+ },
+ "autoload": {
+ "classmap": [
+ "source/"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ *
+ * Interface class of the phpCAS library
+ * PHP Version 5
+ *
+ * @file CAS/CAS.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author Brett Bieber <brett.bieber@gmail.com>
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ * @ingroup public
+ */
+
+
+//
+// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI']
+// in IIS
+//
+if (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['QUERY_STRING'])) {
+ $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
+}
+
+// Add a E_USER_DEPRECATED for php versions <= 5.2
+if (!defined('E_USER_DEPRECATED')) {
+ define('E_USER_DEPRECATED', E_USER_NOTICE);
+}
+
+
+// ########################################################################
+// CONSTANTS
+// ########################################################################
+
+// ------------------------------------------------------------------------
+// CAS VERSIONS
+// ------------------------------------------------------------------------
+
+/**
+ * phpCAS version. accessible for the user by phpCAS::getVersion().
+ */
+define('PHPCAS_VERSION', '1.3.7');
+
+/**
+ * @addtogroup public
+ * @{
+ */
+
+/**
+ * phpCAS supported protocols. accessible for the user by phpCAS::getSupportedProtocols().
+ */
+
+/**
+ * CAS version 1.0
+ */
+define("CAS_VERSION_1_0", '1.0');
+/*!
+ * CAS version 2.0
+*/
+define("CAS_VERSION_2_0", '2.0');
+/**
+ * CAS version 3.0
+ */
+define("CAS_VERSION_3_0", '3.0');
+
+// ------------------------------------------------------------------------
+// SAML defines
+// ------------------------------------------------------------------------
+
+/**
+ * SAML protocol
+ */
+define("SAML_VERSION_1_1", 'S1');
+
+/**
+ * XML header for SAML POST
+ */
+define("SAML_XML_HEADER", '<?xml version="1.0" encoding="UTF-8"?>');
+
+/**
+ * SOAP envelope for SAML POST
+ */
+define("SAML_SOAP_ENV", '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/>');
+
+/**
+ * SOAP body for SAML POST
+ */
+define("SAML_SOAP_BODY", '<SOAP-ENV:Body>');
+
+/**
+ * SAMLP request
+ */
+define("SAMLP_REQUEST", '<samlp:Request xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" MajorVersion="1" MinorVersion="1" RequestID="_192.168.16.51.1024506224022" IssueInstant="2002-06-19T17:03:44.022Z">');
+define("SAMLP_REQUEST_CLOSE", '</samlp:Request>');
+
+/**
+ * SAMLP artifact tag (for the ticket)
+ */
+define("SAML_ASSERTION_ARTIFACT", '<samlp:AssertionArtifact>');
+
+/**
+ * SAMLP close
+ */
+define("SAML_ASSERTION_ARTIFACT_CLOSE", '</samlp:AssertionArtifact>');
+
+/**
+ * SOAP body close
+ */
+define("SAML_SOAP_BODY_CLOSE", '</SOAP-ENV:Body>');
+
+/**
+ * SOAP envelope close
+ */
+define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');
+
+/**
+ * SAML Attributes
+ */
+define("SAML_ATTRIBUTES", 'SAMLATTRIBS');
+
+/**
+ * SAML Attributes
+ */
+define("DEFAULT_ERROR", 'Internal script failure');
+
+/** @} */
+/**
+ * @addtogroup publicPGTStorage
+ * @{
+ */
+// ------------------------------------------------------------------------
+// FILE PGT STORAGE
+// ------------------------------------------------------------------------
+/**
+ * Default path used when storing PGT's to file
+ */
+define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", session_save_path());
+/** @} */
+// ------------------------------------------------------------------------
+// SERVICE ACCESS ERRORS
+// ------------------------------------------------------------------------
+/**
+ * @addtogroup publicServices
+ * @{
+ */
+
+/**
+ * phpCAS::service() error code on success
+ */
+define("PHPCAS_SERVICE_OK", 0);
+/**
+ * phpCAS::service() error code when the PT could not retrieve because
+ * the CAS server did not respond.
+ */
+define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1);
+/**
+ * phpCAS::service() error code when the PT could not retrieve because
+ * the response of the CAS server was ill-formed.
+ */
+define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2);
+/**
+ * phpCAS::service() error code when the PT could not retrieve because
+ * the CAS server did not want to.
+ */
+define("PHPCAS_SERVICE_PT_FAILURE", 3);
+/**
+ * phpCAS::service() error code when the service was not available.
+ */
+define("PHPCAS_SERVICE_NOT_AVAILABLE", 4);
+
+// ------------------------------------------------------------------------
+// SERVICE TYPES
+// ------------------------------------------------------------------------
+/**
+ * phpCAS::getProxiedService() type for HTTP GET
+ */
+define("PHPCAS_PROXIED_SERVICE_HTTP_GET", 'CAS_ProxiedService_Http_Get');
+/**
+ * phpCAS::getProxiedService() type for HTTP POST
+ */
+define("PHPCAS_PROXIED_SERVICE_HTTP_POST", 'CAS_ProxiedService_Http_Post');
+/**
+ * phpCAS::getProxiedService() type for IMAP
+ */
+define("PHPCAS_PROXIED_SERVICE_IMAP", 'CAS_ProxiedService_Imap');
+
+
+/** @} */
+// ------------------------------------------------------------------------
+// LANGUAGES
+// ------------------------------------------------------------------------
+/**
+ * @addtogroup publicLang
+ * @{
+ */
+
+define("PHPCAS_LANG_ENGLISH", 'CAS_Languages_English');
+define("PHPCAS_LANG_FRENCH", 'CAS_Languages_French');
+define("PHPCAS_LANG_GREEK", 'CAS_Languages_Greek');
+define("PHPCAS_LANG_GERMAN", 'CAS_Languages_German');
+define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese');
+define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish');
+define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan');
+define("PHPCAS_LANG_CHINESE_SIMPLIFIED", 'CAS_Languages_ChineseSimplified');
+
+/** @} */
+
+/**
+ * @addtogroup internalLang
+ * @{
+ */
+
+/**
+ * phpCAS default language (when phpCAS::setLang() is not used)
+ */
+define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH);
+
+/** @} */
+// ------------------------------------------------------------------------
+// DEBUG
+// ------------------------------------------------------------------------
+/**
+ * @addtogroup publicDebug
+ * @{
+ */
+
+/**
+ * The default directory for the debug file under Unix.
+ * @return string directory for the debug file
+ */
+function gettmpdir() {
+if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); }
+if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); }
+if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); }
+return "/tmp";
+}
+define('DEFAULT_DEBUG_DIR', gettmpdir()."/");
+
+/** @} */
+
+// include the class autoloader
+require_once dirname(__FILE__) . '/CAS/Autoload.php';
+
+/**
+ * The phpCAS class is a simple container for the phpCAS library. It provides CAS
+ * authentication for web applications written in PHP.
+ *
+ * @ingroup public
+ * @class phpCAS
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author Brett Bieber <brett.bieber@gmail.com>
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class phpCAS
+{
+
+ /**
+ * This variable is used by the interface class phpCAS.
+ *
+ * @var CAS_Client
+ * @hideinitializer
+ */
+ private static $_PHPCAS_CLIENT;
+
+ /**
+ * @var array
+ * This variable is used to store where the initializer is called from
+ * (to print a comprehensive error in case of multiple calls).
+ *
+ * @hideinitializer
+ */
+ private static $_PHPCAS_INIT_CALL;
+
+ /**
+ * @var array
+ * This variable is used to store phpCAS debug mode.
+ *
+ * @hideinitializer
+ */
+ private static $_PHPCAS_DEBUG;
+
+ /**
+ * This variable is used to enable verbose mode
+ * This pevents debug info to be show to the user. Since it's a security
+ * feature the default is false
+ *
+ * @hideinitializer
+ */
+ private static $_PHPCAS_VERBOSE = false;
+
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * @addtogroup publicInit
+ * @{
+ */
+
+ /**
+ * phpCAS client initializer.
+ *
+ * @param string $server_version the version of the CAS server
+ * @param string $server_hostname the hostname of the CAS server
+ * @param int $server_port the port the CAS server is running on
+ * @param string $server_uri the URI the CAS server is responding on
+ * @param bool $changeSessionID Allow phpCAS to change the session_id (Single
+ * Sign Out/handleLogoutRequests is based on that change)
+ *
+ * @return void a newly created CAS_Client object
+ * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
+ * called, only once, and before all other methods (except phpCAS::getVersion()
+ * and phpCAS::setDebug()).
+ */
+ public static function client($server_version, $server_hostname,
+ $server_port, $server_uri, $changeSessionID = true
+ ) {
+ phpCAS :: traceBegin();
+ if (is_object(self::$_PHPCAS_CLIENT)) {
+ phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
+ }
+
+ // store where the initializer is called from
+ $dbg = debug_backtrace();
+ self::$_PHPCAS_INIT_CALL = array (
+ 'done' => true,
+ 'file' => $dbg[0]['file'],
+ 'line' => $dbg[0]['line'],
+ 'method' => __CLASS__ . '::' . __FUNCTION__
+ );
+
+ // initialize the object $_PHPCAS_CLIENT
+ try {
+ self::$_PHPCAS_CLIENT = new CAS_Client(
+ $server_version, false, $server_hostname, $server_port, $server_uri,
+ $changeSessionID
+ );
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * phpCAS proxy initializer.
+ *
+ * @param string $server_version the version of the CAS server
+ * @param string $server_hostname the hostname of the CAS server
+ * @param int $server_port the port the CAS server is running on
+ * @param string $server_uri the URI the CAS server is responding on
+ * @param bool $changeSessionID Allow phpCAS to change the session_id (Single
+ * Sign Out/handleLogoutRequests is based on that change)
+ *
+ * @return void a newly created CAS_Client object
+ * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
+ * called, only once, and before all other methods (except phpCAS::getVersion()
+ * and phpCAS::setDebug()).
+ */
+ public static function proxy($server_version, $server_hostname,
+ $server_port, $server_uri, $changeSessionID = true
+ ) {
+ phpCAS :: traceBegin();
+ if (is_object(self::$_PHPCAS_CLIENT)) {
+ phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
+ }
+
+ // store where the initialzer is called from
+ $dbg = debug_backtrace();
+ self::$_PHPCAS_INIT_CALL = array (
+ 'done' => true,
+ 'file' => $dbg[0]['file'],
+ 'line' => $dbg[0]['line'],
+ 'method' => __CLASS__ . '::' . __FUNCTION__
+ );
+
+ // initialize the object $_PHPCAS_CLIENT
+ try {
+ self::$_PHPCAS_CLIENT = new CAS_Client(
+ $server_version, true, $server_hostname, $server_port, $server_uri,
+ $changeSessionID
+ );
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Answer whether or not the client or proxy has been initialized
+ *
+ * @return bool
+ */
+ public static function isInitialized ()
+ {
+ return (is_object(self::$_PHPCAS_CLIENT));
+ }
+
+ /** @} */
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * @addtogroup publicDebug
+ * @{
+ */
+
+ /**
+ * Set/unset debug mode
+ *
+ * @param string $filename the name of the file used for logging, or false
+ * to stop debugging.
+ *
+ * @return void
+ */
+ public static function setDebug($filename = '')
+ {
+ if ($filename != false && gettype($filename) != 'string') {
+ phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)');
+ }
+ if ($filename === false) {
+ self::$_PHPCAS_DEBUG['filename'] = false;
+
+ } else {
+ if (empty ($filename)) {
+ if (preg_match('/^Win.*/', getenv('OS'))) {
+ if (isset ($_ENV['TMP'])) {
+ $debugDir = $_ENV['TMP'] . '/';
+ } else {
+ $debugDir = '';
+ }
+ } else {
+ $debugDir = DEFAULT_DEBUG_DIR;
+ }
+ $filename = $debugDir . 'phpCAS.log';
+ }
+
+ if (empty (self::$_PHPCAS_DEBUG['unique_id'])) {
+ self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);
+ }
+
+ self::$_PHPCAS_DEBUG['filename'] = $filename;
+ self::$_PHPCAS_DEBUG['indent'] = 0;
+
+ phpCAS :: trace('START ('.date("Y-m-d H:i:s").') phpCAS-' . PHPCAS_VERSION . ' ******************');
+ }
+ }
+
+ /**
+ * Enable verbose errors messages in the website output
+ * This is a security relevant since internal status info may leak an may
+ * help an attacker. Default is therefore false
+ *
+ * @param bool $verbose enable verbose output
+ *
+ * @return void
+ */
+ public static function setVerbose($verbose)
+ {
+ if ($verbose === true) {
+ self::$_PHPCAS_VERBOSE = true;
+ } else {
+ self::$_PHPCAS_VERBOSE = false;
+ }
+ }
+
+
+ /**
+ * Show is verbose mode is on
+ *
+ * @return bool verbose
+ */
+ public static function getVerbose()
+ {
+ return self::$_PHPCAS_VERBOSE;
+ }
+
+ /**
+ * Logs a string in debug mode.
+ *
+ * @param string $str the string to write
+ *
+ * @return void
+ * @private
+ */
+ public static function log($str)
+ {
+ $indent_str = ".";
+
+
+ if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
+ // Check if file exists and modifiy file permissions to be only
+ // readable by the webserver
+ if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
+ touch(self::$_PHPCAS_DEBUG['filename']);
+ // Chmod will fail on windows
+ @chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
+ }
+ for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) {
+
+ $indent_str .= '| ';
+ }
+ // allow for multiline output with proper identing. Usefull for
+ // dumping cas answers etc.
+ $str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str);
+ error_log(self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
+ }
+
+ }
+
+ /**
+ * This method is used by interface methods to print an error and where the
+ * function was originally called from.
+ *
+ * @param string $msg the message to print
+ *
+ * @return void
+ * @private
+ */
+ public static function error($msg)
+ {
+ phpCAS :: traceBegin();
+ $dbg = debug_backtrace();
+ $function = '?';
+ $file = '?';
+ $line = '?';
+ if (is_array($dbg)) {
+ for ($i = 1; $i < sizeof($dbg); $i++) {
+ if (is_array($dbg[$i]) && isset($dbg[$i]['class']) ) {
+ if ($dbg[$i]['class'] == __CLASS__) {
+ $function = $dbg[$i]['function'];
+ $file = $dbg[$i]['file'];
+ $line = $dbg[$i]['line'];
+ }
+ }
+ }
+ }
+ if (self::$_PHPCAS_VERBOSE) {
+ echo "<br />\n<b>phpCAS error</b>: <font color=\"FF0000\"><b>" . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . "</b></font> in <b>" . $file . "</b> on line <b>" . $line . "</b><br />\n";
+ } else {
+ echo "<br />\n<b>Error</b>: <font color=\"FF0000\"><b>". DEFAULT_ERROR ."</b><br />\n";
+ }
+ phpCAS :: trace($msg . ' in ' . $file . 'on line ' . $line );
+ phpCAS :: traceEnd();
+
+ throw new CAS_GracefullTerminationException(__CLASS__ . "::" . $function . '(): ' . $msg);
+ }
+
+ /**
+ * This method is used to log something in debug mode.
+ *
+ * @param string $str string to log
+ *
+ * @return void
+ */
+ public static function trace($str)
+ {
+ $dbg = debug_backtrace();
+ phpCAS :: log($str . ' [' . basename($dbg[0]['file']) . ':' . $dbg[0]['line'] . ']');
+ }
+
+ /**
+ * This method is used to indicate the start of the execution of a function
+ * in debug mode.
+ *
+ * @return void
+ */
+ public static function traceBegin()
+ {
+ $dbg = debug_backtrace();
+ $str = '=> ';
+ if (!empty ($dbg[1]['class'])) {
+ $str .= $dbg[1]['class'] . '::';
+ }
+ $str .= $dbg[1]['function'] . '(';
+ if (is_array($dbg[1]['args'])) {
+ foreach ($dbg[1]['args'] as $index => $arg) {
+ if ($index != 0) {
+ $str .= ', ';
+ }
+ if (is_object($arg)) {
+ $str .= get_class($arg);
+ } else {
+ $str .= str_replace(array("\r\n", "\n", "\r"), "", var_export($arg, true));
+ }
+ }
+ }
+ if (isset($dbg[1]['file'])) {
+ $file = basename($dbg[1]['file']);
+ } else {
+ $file = 'unknown_file';
+ }
+ if (isset($dbg[1]['line'])) {
+ $line = $dbg[1]['line'];
+ } else {
+ $line = 'unknown_line';
+ }
+ $str .= ') [' . $file . ':' . $line . ']';
+ phpCAS :: log($str);
+ if (!isset(self::$_PHPCAS_DEBUG['indent'])) {
+ self::$_PHPCAS_DEBUG['indent'] = 0;
+ } else {
+ self::$_PHPCAS_DEBUG['indent']++;
+ }
+ }
+
+ /**
+ * This method is used to indicate the end of the execution of a function in
+ * debug mode.
+ *
+ * @param mixed $res the result of the function
+ *
+ * @return void
+ */
+ public static function traceEnd($res = '')
+ {
+ if (empty(self::$_PHPCAS_DEBUG['indent'])) {
+ self::$_PHPCAS_DEBUG['indent'] = 0;
+ } else {
+ self::$_PHPCAS_DEBUG['indent']--;
+ }
+ $str = '';
+ if (is_object($res)) {
+ $str .= '<= ' . get_class($res);
+ } else {
+ $str .= '<= ' . str_replace(array("\r\n", "\n", "\r"), "", var_export($res, true));
+ }
+
+ phpCAS :: log($str);
+ }
+
+ /**
+ * This method is used to indicate the end of the execution of the program
+ *
+ * @return void
+ */
+ public static function traceExit()
+ {
+ phpCAS :: log('exit()');
+ while (self::$_PHPCAS_DEBUG['indent'] > 0) {
+ phpCAS :: log('-');
+ self::$_PHPCAS_DEBUG['indent']--;
+ }
+ }
+
+ /** @} */
+ // ########################################################################
+ // INTERNATIONALIZATION
+ // ########################################################################
+ /**
+ * @addtogroup publicLang
+ * @{
+ */
+
+ /**
+ * This method is used to set the language used by phpCAS.
+ *
+ * @param string $lang string representing the language.
+ *
+ * @return void
+ *
+ * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH
+ * @note Can be called only once.
+ */
+ public static function setLang($lang)
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setLang($lang);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /** @} */
+ // ########################################################################
+ // VERSION
+ // ########################################################################
+ /**
+ * @addtogroup public
+ * @{
+ */
+
+ /**
+ * This method returns the phpCAS version.
+ *
+ * @return string the phpCAS version.
+ */
+ public static function getVersion()
+ {
+ return PHPCAS_VERSION;
+ }
+
+ /**
+ * This method returns supported protocols.
+ *
+ * @return array an array of all supported protocols. Use internal protocol name as array key.
+ */
+ public static function getSupportedProtocols()
+ {
+ $supportedProtocols = array();
+ $supportedProtocols[CAS_VERSION_1_0] = 'CAS 1.0';
+ $supportedProtocols[CAS_VERSION_2_0] = 'CAS 2.0';
+ $supportedProtocols[CAS_VERSION_3_0] = 'CAS 3.0';
+ $supportedProtocols[SAML_VERSION_1_1] = 'SAML 1.1';
+
+ return $supportedProtocols;
+ }
+
+ /** @} */
+ // ########################################################################
+ // HTML OUTPUT
+ // ########################################################################
+ /**
+ * @addtogroup publicOutput
+ * @{
+ */
+
+ /**
+ * This method sets the HTML header used for all outputs.
+ *
+ * @param string $header the HTML header.
+ *
+ * @return void
+ */
+ public static function setHTMLHeader($header)
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setHTMLHeader($header);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * This method sets the HTML footer used for all outputs.
+ *
+ * @param string $footer the HTML footer.
+ *
+ * @return void
+ */
+ public static function setHTMLFooter($footer)
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setHTMLFooter($footer);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /** @} */
+ // ########################################################################
+ // PGT STORAGE
+ // ########################################################################
+ /**
+ * @addtogroup publicPGTStorage
+ * @{
+ */
+
+ /**
+ * This method can be used to set a custom PGT storage object.
+ *
+ * @param CAS_PGTStorage_AbstractStorage $storage a PGT storage object that inherits from the
+ * CAS_PGTStorage_AbstractStorage class
+ *
+ * @return void
+ */
+ public static function setPGTStorage($storage)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setPGTStorage($storage);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is used to tell phpCAS to store the response of the
+ * CAS server to PGT requests in a database.
+ *
+ * @param string $dsn_or_pdo a dsn string to use for creating a PDO
+ * object or a PDO object
+ * @param string $username the username to use when connecting to the
+ * database
+ * @param string $password the password to use when connecting to the
+ * database
+ * @param string $table the table to use for storing and retrieving
+ * PGT's
+ * @param string $driver_options any driver options to use when connecting
+ * to the database
+ *
+ * @return void
+ */
+ public static function setPGTStorageDb($dsn_or_pdo, $username='',
+ $password='', $table='', $driver_options=null
+ ) {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setPGTStorageDb($dsn_or_pdo, $username, $password, $table, $driver_options);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is used to tell phpCAS to store the response of the
+ * CAS server to PGT requests onto the filesystem.
+ *
+ * @param string $path the path where the PGT's should be stored
+ *
+ * @return void
+ */
+ public static function setPGTStorageFile($path = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setPGTStorageFile($path);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ phpCAS :: traceEnd();
+ }
+ /** @} */
+ // ########################################################################
+ // ACCESS TO EXTERNAL SERVICES
+ // ########################################################################
+ /**
+ * @addtogroup publicServices
+ * @{
+ */
+
+ /**
+ * Answer a proxy-authenticated service handler.
+ *
+ * @param string $type The service type. One of
+ * PHPCAS_PROXIED_SERVICE_HTTP_GET; PHPCAS_PROXIED_SERVICE_HTTP_POST;
+ * PHPCAS_PROXIED_SERVICE_IMAP
+ *
+ * @return CAS_ProxiedService
+ * @throws InvalidArgumentException If the service type is unknown.
+ */
+ public static function getProxiedService ($type)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ $res = self::$_PHPCAS_CLIENT->getProxiedService($type);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ return $res;
+ }
+
+ /**
+ * Initialize a proxied-service handler with the proxy-ticket it should use.
+ *
+ * @param CAS_ProxiedService $proxiedService Proxied Service Handler
+ *
+ * @return void
+ * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
+ * The code of the Exception will be one of:
+ * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_FAILURE
+ */
+ public static function initializeProxiedService (CAS_ProxiedService $proxiedService)
+ {
+ phpCAS::_validateProxyExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->initializeProxiedService($proxiedService);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * This method is used to access an HTTP[S] service.
+ *
+ * @param string $url the service to access.
+ * @param int &$err_code an error code Possible values are
+ * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
+ * PHPCAS_SERVICE_NOT_AVAILABLE.
+ * @param string &$output the output of the service (also used to give an
+ * error message on failure).
+ *
+ * @return bool true on success, false otherwise (in this later case,
+ * $err_code gives the reason why it failed and $output contains an error
+ * message).
+ */
+ public static function serviceWeb($url, & $err_code, & $output)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ $res = self::$_PHPCAS_CLIENT->serviceWeb($url, $err_code, $output);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd($res);
+ return $res;
+ }
+
+ /**
+ * This method is used to access an IMAP/POP3/NNTP service.
+ *
+ * @param string $url a string giving the URL of the service,
+ * including the mailing box for IMAP URLs, as accepted by imap_open().
+ * @param string $service a string giving for CAS retrieve Proxy ticket
+ * @param string $flags options given to imap_open().
+ * @param int &$err_code an error code Possible values are
+ * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
+ * PHPCAS_SERVICE_NOT_AVAILABLE.
+ * @param string &$err_msg an error message on failure
+ * @param string &$pt the Proxy Ticket (PT) retrieved from the CAS
+ * server to access the URL on success, false on error).
+ *
+ * @return object|false IMAP stream on success, false otherwise (in this later
+ * case, $err_code gives the reason why it failed and $err_msg contains an
+ * error message).
+ */
+ public static function serviceMail($url, $service, $flags, & $err_code, & $err_msg, & $pt)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ $res = self::$_PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd($res);
+ return $res;
+ }
+
+ /** @} */
+ // ########################################################################
+ // AUTHENTICATION
+ // ########################################################################
+ /**
+ * @addtogroup publicAuth
+ * @{
+ */
+
+ /**
+ * Set the times authentication will be cached before really accessing the
+ * CAS server in gateway mode:
+ * - -1: check only once, and then never again (until you pree login)
+ * - 0: always check
+ * - n: check every "n" time
+ *
+ * @param int $n an integer.
+ *
+ * @return void
+ */
+ public static function setCacheTimesForAuthRecheck($n)
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+
+ /**
+ * Set a callback function to be run when receiving CAS attributes
+ *
+ * The callback function will be passed an $success_elements
+ * payload of the response (\DOMElement) as its first parameter.
+ *
+ * @param string $function Callback function
+ * @param array $additionalArgs optional array of arguments
+ *
+ * @return void
+ */
+ public static function setCasAttributeParserCallback($function, array $additionalArgs = array())
+ {
+ phpCAS::_validateClientExists();
+
+ self::$_PHPCAS_CLIENT->setCasAttributeParserCallback($function, $additionalArgs);
+ }
+
+ /**
+ * Set a callback function to be run when a user authenticates.
+ *
+ * The callback function will be passed a $logoutTicket as its first
+ * parameter, followed by any $additionalArgs you pass. The $logoutTicket
+ * parameter is an opaque string that can be used to map the session-id to
+ * logout request in order to support single-signout in applications that
+ * manage their own sessions (rather than letting phpCAS start the session).
+ *
+ * phpCAS::forceAuthentication() will always exit and forward client unless
+ * they are already authenticated. To perform an action at the moment the user
+ * logs in (such as registering an account, performing logging, etc), register
+ * a callback function here.
+ *
+ * @param callable $function Callback function
+ * @param array $additionalArgs optional array of arguments
+ *
+ * @return void
+ */
+ public static function setPostAuthenticateCallback ($function, array $additionalArgs = array())
+ {
+ phpCAS::_validateClientExists();
+
+ self::$_PHPCAS_CLIENT->setPostAuthenticateCallback($function, $additionalArgs);
+ }
+
+ /**
+ * Set a callback function to be run when a single-signout request is
+ * received. The callback function will be passed a $logoutTicket as its
+ * first parameter, followed by any $additionalArgs you pass. The
+ * $logoutTicket parameter is an opaque string that can be used to map a
+ * session-id to the logout request in order to support single-signout in
+ * applications that manage their own sessions (rather than letting phpCAS
+ * start and destroy the session).
+ *
+ * @param callable $function Callback function
+ * @param array $additionalArgs optional array of arguments
+ *
+ * @return void
+ */
+ public static function setSingleSignoutCallback ($function, array $additionalArgs = array())
+ {
+ phpCAS::_validateClientExists();
+
+ self::$_PHPCAS_CLIENT->setSingleSignoutCallback($function, $additionalArgs);
+ }
+
+ /**
+ * This method is called to check if the user is already authenticated
+ * locally or has a global cas session. A already existing cas session is
+ * determined by a cas gateway call.(cas login call without any interactive
+ * prompt)
+ *
+ * @return bool true when the user is authenticated, false when a previous
+ * gateway login failed or the function will not return if the user is
+ * redirected to the cas server for a gateway login attempt
+ */
+ public static function checkAuthentication()
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ $auth = self::$_PHPCAS_CLIENT->checkAuthentication();
+
+ // store where the authentication has been checked and the result
+ self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+ phpCAS :: traceEnd($auth);
+ return $auth;
+ }
+
+ /**
+ * This method is called to force authentication if the user was not already
+ * authenticated. If the user is not authenticated, halt by redirecting to
+ * the CAS server.
+ *
+ * @return bool Authentication
+ */
+ public static function forceAuthentication()
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+ $auth = self::$_PHPCAS_CLIENT->forceAuthentication();
+
+ // store where the authentication has been checked and the result
+ self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+ /* if (!$auth) {
+ phpCAS :: trace('user is not authenticated, redirecting to the CAS server');
+ self::$_PHPCAS_CLIENT->forceAuthentication();
+ } else {
+ phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)');
+ }*/
+
+ phpCAS :: traceEnd();
+ return $auth;
+ }
+
+ /**
+ * This method is called to renew the authentication.
+ *
+ * @return void
+ **/
+ public static function renewAuthentication()
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ $auth = self::$_PHPCAS_CLIENT->renewAuthentication();
+
+ // store where the authentication has been checked and the result
+ self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+ //self::$_PHPCAS_CLIENT->renewAuthentication();
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is called to check if the user is authenticated (previously or by
+ * tickets given in the URL).
+ *
+ * @return bool true when the user is authenticated.
+ */
+ public static function isAuthenticated()
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ // call the isAuthenticated method of the $_PHPCAS_CLIENT object
+ $auth = self::$_PHPCAS_CLIENT->isAuthenticated();
+
+ // store where the authentication has been checked and the result
+ self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+ phpCAS :: traceEnd($auth);
+ return $auth;
+ }
+
+ /**
+ * Checks whether authenticated based on $_SESSION. Useful to avoid
+ * server calls.
+ *
+ * @return bool true if authenticated, false otherwise.
+ * @since 0.4.22 by Brendan Arnold
+ */
+ public static function isSessionAuthenticated()
+ {
+ phpCAS::_validateClientExists();
+
+ return (self::$_PHPCAS_CLIENT->isSessionAuthenticated());
+ }
+
+ /**
+ * This method returns the CAS user's login name.
+ *
+ * @return string the login name of the authenticated user
+ * @warning should only be called after phpCAS::forceAuthentication()
+ * or phpCAS::checkAuthentication().
+ * */
+ public static function getUser()
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ return self::$_PHPCAS_CLIENT->getUser();
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Answer attributes about the authenticated user.
+ *
+ * @warning should only be called after phpCAS::forceAuthentication()
+ * or phpCAS::checkAuthentication().
+ *
+ * @return array
+ */
+ public static function getAttributes()
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ return self::$_PHPCAS_CLIENT->getAttributes();
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Answer true if there are attributes for the authenticated user.
+ *
+ * @warning should only be called after phpCAS::forceAuthentication()
+ * or phpCAS::checkAuthentication().
+ *
+ * @return bool
+ */
+ public static function hasAttributes()
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ return self::$_PHPCAS_CLIENT->hasAttributes();
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Answer true if an attribute exists for the authenticated user.
+ *
+ * @param string $key attribute name
+ *
+ * @return bool
+ * @warning should only be called after phpCAS::forceAuthentication()
+ * or phpCAS::checkAuthentication().
+ */
+ public static function hasAttribute($key)
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ return self::$_PHPCAS_CLIENT->hasAttribute($key);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Answer an attribute for the authenticated user.
+ *
+ * @param string $key attribute name
+ *
+ * @return mixed string for a single value or an array if multiple values exist.
+ * @warning should only be called after phpCAS::forceAuthentication()
+ * or phpCAS::checkAuthentication().
+ */
+ public static function getAttribute($key)
+ {
+ phpCAS::_validateClientExists();
+
+ try {
+ return self::$_PHPCAS_CLIENT->getAttribute($key);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Handle logout requests.
+ *
+ * @param bool $check_client additional safety check
+ * @param array $allowed_clients array of allowed clients
+ *
+ * @return void
+ */
+ public static function handleLogoutRequests($check_client = true, $allowed_clients = array())
+ {
+ phpCAS::_validateClientExists();
+
+ return (self::$_PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients));
+ }
+
+ /**
+ * This method returns the URL to be used to login.
+ *
+ * @return string the login URL
+ */
+ public static function getServerLoginURL()
+ {
+ phpCAS::_validateClientExists();
+
+ return self::$_PHPCAS_CLIENT->getServerLoginURL();
+ }
+
+ /**
+ * Set the login URL of the CAS server.
+ *
+ * @param string $url the login URL
+ *
+ * @return void
+ * @since 0.4.21 by Wyman Chan
+ */
+ public static function setServerLoginURL($url = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setServerLoginURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set the serviceValidate URL of the CAS server.
+ * Used for all CAS versions of URL validations.
+ * Examples:
+ * CAS 1.0 http://www.exemple.com/validate
+ * CAS 2.0 http://www.exemple.com/validateURL
+ * CAS 3.0 http://www.exemple.com/p3/serviceValidate
+ *
+ * @param string $url the serviceValidate URL
+ *
+ * @return void
+ */
+ public static function setServerServiceValidateURL($url = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setServerServiceValidateURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set the proxyValidate URL of the CAS server.
+ * Used for all CAS versions of proxy URL validations
+ * Examples:
+ * CAS 1.0 http://www.exemple.com/
+ * CAS 2.0 http://www.exemple.com/proxyValidate
+ * CAS 3.0 http://www.exemple.com/p3/proxyValidate
+ *
+ * @param string $url the proxyValidate URL
+ *
+ * @return void
+ */
+ public static function setServerProxyValidateURL($url = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setServerProxyValidateURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set the samlValidate URL of the CAS server.
+ *
+ * @param string $url the samlValidate URL
+ *
+ * @return void
+ */
+ public static function setServerSamlValidateURL($url = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setServerSamlValidateURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method returns the URL to be used to logout.
+ *
+ * @return string the URL to use to log out
+ */
+ public static function getServerLogoutURL()
+ {
+ phpCAS::_validateClientExists();
+
+ return self::$_PHPCAS_CLIENT->getServerLogoutURL();
+ }
+
+ /**
+ * Set the logout URL of the CAS server.
+ *
+ * @param string $url the logout URL
+ *
+ * @return void
+ * @since 0.4.21 by Wyman Chan
+ */
+ public static function setServerLogoutURL($url = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setServerLogoutURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is used to logout from CAS.
+ *
+ * @param string $params an array that contains the optional url and
+ * service parameters that will be passed to the CAS server
+ *
+ * @return void
+ */
+ public static function logout($params = "")
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ $parsedParams = array ();
+ if ($params != "") {
+ if (is_string($params)) {
+ phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead');
+ }
+ if (!is_array($params)) {
+ phpCAS :: error('type mismatched for parameter $params (should be `array\')');
+ }
+ foreach ($params as $key => $value) {
+ if ($key != "service" && $key != "url") {
+ phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\'');
+ }
+ $parsedParams[$key] = $value;
+ }
+ }
+ self::$_PHPCAS_CLIENT->logout($parsedParams);
+ // never reached
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is used to logout from CAS. Halts by redirecting to the CAS
+ * server.
+ *
+ * @param string $service a URL that will be transmitted to the CAS server
+ *
+ * @return void
+ */
+ public static function logoutWithRedirectService($service)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ if (!is_string($service)) {
+ phpCAS :: error('type mismatched for parameter $service (should be `string\')');
+ }
+ self::$_PHPCAS_CLIENT->logout(array ( "service" => $service ));
+ // never reached
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is used to logout from CAS. Halts by redirecting to the CAS
+ * server.
+ *
+ * @param string $url a URL that will be transmitted to the CAS server
+ *
+ * @return void
+ * @deprecated The url parameter has been removed from the CAS server as of
+ * version 3.3.5.1
+ */
+ public static function logoutWithUrl($url)
+ {
+ trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED);
+ phpCAS :: traceBegin();
+ if (!is_object(self::$_PHPCAS_CLIENT)) {
+ phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+ }
+ if (!is_string($url)) {
+ phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+ }
+ self::$_PHPCAS_CLIENT->logout(array ( "url" => $url ));
+ // never reached
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * This method is used to logout from CAS. Halts by redirecting to the CAS
+ * server.
+ *
+ * @param string $service a URL that will be transmitted to the CAS server
+ * @param string $url a URL that will be transmitted to the CAS server
+ *
+ * @return void
+ *
+ * @deprecated The url parameter has been removed from the CAS server as of
+ * version 3.3.5.1
+ */
+ public static function logoutWithRedirectServiceAndUrl($service, $url)
+ {
+ trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED);
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ if (!is_string($service)) {
+ phpCAS :: error('type mismatched for parameter $service (should be `string\')');
+ }
+ if (!is_string($url)) {
+ phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+ }
+ self::$_PHPCAS_CLIENT->logout(
+ array (
+ "service" => $service,
+ "url" => $url
+ )
+ );
+ // never reached
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set the fixed URL that will be used by the CAS server to transmit the
+ * PGT. When this method is not called, a phpCAS script uses its own URL
+ * for the callback.
+ *
+ * @param string $url the URL
+ *
+ * @return void
+ */
+ public static function setFixedCallbackURL($url = '')
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setCallbackURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set the fixed URL that will be set as the CAS service parameter. When this
+ * method is not called, a phpCAS script uses its own URL.
+ *
+ * @param string $url the URL
+ *
+ * @return void
+ */
+ public static function setFixedServiceURL($url)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateProxyExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setURL($url);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Get the URL that is set as the CAS service parameter.
+ *
+ * @return string Service Url
+ */
+ public static function getServiceURL()
+ {
+ phpCAS::_validateProxyExists();
+ return (self::$_PHPCAS_CLIENT->getURL());
+ }
+
+ /**
+ * Retrieve a Proxy Ticket from the CAS server.
+ *
+ * @param string $target_service Url string of service to proxy
+ * @param int &$err_code error code
+ * @param string &$err_msg error message
+ *
+ * @return string Proxy Ticket
+ */
+ public static function retrievePT($target_service, & $err_code, & $err_msg)
+ {
+ phpCAS::_validateProxyExists();
+
+ try {
+ return (self::$_PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg));
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Set the certificate of the CAS server CA and if the CN should be properly
+ * verified.
+ *
+ * @param string $cert CA certificate file name
+ * @param bool $validate_cn Validate CN in certificate (default true)
+ *
+ * @return void
+ */
+ public static function setCasServerCACert($cert, $validate_cn = true)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->setCasServerCACert($cert, $validate_cn);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set no SSL validation for the CAS server.
+ *
+ * @return void
+ */
+ public static function setNoCasServerValidation()
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ phpCAS :: trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.');
+ self::$_PHPCAS_CLIENT->setNoCasServerValidation();
+ phpCAS :: traceEnd();
+ }
+
+
+ /**
+ * Disable the removal of a CAS-Ticket from the URL when authenticating
+ * DISABLING POSES A SECURITY RISK:
+ * We normally remove the ticket by an additional redirect as a security
+ * precaution to prevent a ticket in the HTTP_REFERRER or be carried over in
+ * the URL parameter
+ *
+ * @return void
+ */
+ public static function setNoClearTicketsFromUrl()
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ self::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl();
+ phpCAS :: traceEnd();
+ }
+
+ /** @} */
+
+ /**
+ * Change CURL options.
+ * CURL is used to connect through HTTPS to CAS server
+ *
+ * @param string $key the option key
+ * @param string $value the value to set
+ *
+ * @return void
+ */
+ public static function setExtraCurlOption($key, $value)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ self::$_PHPCAS_CLIENT->setExtraCurlOption($key, $value);
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Set a salt/seed for the session-id hash to make it harder to guess.
+ *
+ * When $changeSessionID = true phpCAS will create a session-id that is derived
+ * from the service ticket. Doing so allows phpCAS to look-up and destroy the
+ * proper session on single-log-out requests. While the service tickets
+ * provided by the CAS server may include enough data to generate a strong
+ * hash, clients may provide an additional salt to ensure that session ids
+ * are not guessable if the session tickets do not have enough entropy.
+ *
+ * @param string $salt The salt to combine with the session ticket.
+ *
+ * @return void
+ */
+ public static function setSessionIdSalt($salt) {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+ self::$_PHPCAS_CLIENT->setSessionIdSalt($salt);
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * If you want your service to be proxied you have to enable it (default
+ * disabled) and define an accepable list of proxies that are allowed to
+ * proxy your service.
+ *
+ * Add each allowed proxy definition object. For the normal CAS_ProxyChain
+ * class, the constructor takes an array of proxies to match. The list is in
+ * reverse just as seen from the service. Proxies have to be defined in reverse
+ * from the service to the user. If a user hits service A and gets proxied via
+ * B to service C the list of acceptable on C would be array(B,A). The definition
+ * of an individual proxy can be either a string or a regexp (preg_match is used)
+ * that will be matched against the proxy list supplied by the cas server
+ * when validating the proxy tickets. The strings are compared starting from
+ * the beginning and must fully match with the proxies in the list.
+ * Example:
+ * phpCAS::allowProxyChain(new CAS_ProxyChain(array(
+ * 'https://app.example.com/'
+ * )));
+ * phpCAS::allowProxyChain(new CAS_ProxyChain(array(
+ * '/^https:\/\/app[0-9]\.example\.com\/rest\//',
+ * 'http://client.example.com/'
+ * )));
+ *
+ * For quick testing or in certain production screnarios you might want to
+ * allow allow any other valid service to proxy your service. To do so, add
+ * the "Any" chain:
+ * phpCAS::allowProxyChain(new CAS_ProxyChain_Any);
+ * THIS SETTING IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY
+ * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER
+ * ON THIS SERVICE.
+ *
+ * @param CAS_ProxyChain_Interface $proxy_chain A proxy-chain that will be
+ * matched against the proxies requesting access
+ *
+ * @return void
+ */
+ public static function allowProxyChain(CAS_ProxyChain_Interface $proxy_chain)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ if (self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_2_0
+ && self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_3_0
+ ) {
+ phpCAS :: error('this method can only be used with the cas 2.0/3.0 protocols');
+ }
+ self::$_PHPCAS_CLIENT->getAllowedProxyChains()->allowProxyChain($proxy_chain);
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Answer an array of proxies that are sitting in front of this application.
+ * This method will only return a non-empty array if we have received and
+ * validated a Proxy Ticket.
+ *
+ * @return array
+ * @access public
+ * @since 6/25/09
+ */
+ public static function getProxies ()
+ {
+ phpCAS::_validateProxyExists();
+
+ return(self::$_PHPCAS_CLIENT->getProxies());
+ }
+
+ // ########################################################################
+ // PGTIOU/PGTID and logoutRequest rebroadcasting
+ // ########################################################################
+
+ /**
+ * Add a pgtIou/pgtId and logoutRequest rebroadcast node.
+ *
+ * @param string $rebroadcastNodeUrl The rebroadcast node URL. Can be
+ * hostname or IP.
+ *
+ * @return void
+ */
+ public static function addRebroadcastNode($rebroadcastNodeUrl)
+ {
+ phpCAS::traceBegin();
+ phpCAS::log('rebroadcastNodeUrl:'.$rebroadcastNodeUrl);
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->addRebroadcastNode($rebroadcastNodeUrl);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method is used to add header parameters when rebroadcasting
+ * pgtIou/pgtId or logoutRequest.
+ *
+ * @param String $header Header to send when rebroadcasting.
+ *
+ * @return void
+ */
+ public static function addRebroadcastHeader($header)
+ {
+ phpCAS :: traceBegin();
+ phpCAS::_validateClientExists();
+
+ try {
+ self::$_PHPCAS_CLIENT->addRebroadcastHeader($header);
+ } catch (Exception $e) {
+ phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
+ }
+
+ phpCAS :: traceEnd();
+ }
+
+ /**
+ * Checks if a client already exists
+ *
+ * @throws CAS_OutOfSequenceBeforeClientException
+ *
+ * @return void
+ */
+ private static function _validateClientExists()
+ {
+ if (!is_object(self::$_PHPCAS_CLIENT)) {
+ throw new CAS_OutOfSequenceBeforeClientException();
+ }
+ }
+
+ /**
+ * Checks of a proxy client aready exists
+ *
+ * @throws CAS_OutOfSequenceBeforeProxyException
+ *
+ * @return void
+ */
+ private static function _validateProxyExists()
+ {
+ if (!is_object(self::$_PHPCAS_CLIENT)) {
+ throw new CAS_OutOfSequenceBeforeProxyException();
+ }
+ }
+
+ /**
+ * For testing purposes, use this method to set the client to a test double
+ *
+ * @return void
+ */
+ public static function setCasClient(\CAS_Client $client)
+ {
+ self::$_PHPCAS_CLIENT = $client;
+ }
+}
+// ########################################################################
+// DOCUMENTATION
+// ########################################################################
+
+// ########################################################################
+// MAIN PAGE
+
+/**
+ * @mainpage
+ *
+ * The following pages only show the source documentation.
+ *
+ */
+
+// ########################################################################
+// MODULES DEFINITION
+
+/** @defgroup public User interface */
+
+/** @defgroup publicInit Initialization
+ * @ingroup public */
+
+/** @defgroup publicAuth Authentication
+ * @ingroup public */
+
+/** @defgroup publicServices Access to external services
+ * @ingroup public */
+
+/** @defgroup publicConfig Configuration
+ * @ingroup public */
+
+/** @defgroup publicLang Internationalization
+ * @ingroup publicConfig */
+
+/** @defgroup publicOutput HTML output
+ * @ingroup publicConfig */
+
+/** @defgroup publicPGTStorage PGT storage
+ * @ingroup publicConfig */
+
+/** @defgroup publicDebug Debugging
+ * @ingroup public */
+
+/** @defgroup internal Implementation */
+
+/** @defgroup internalAuthentication Authentication
+ * @ingroup internal */
+
+/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets)
+ * @ingroup internal */
+
+/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets)
+ * @ingroup internal */
+
+/** @defgroup internalSAML CAS SAML features (SAML 1.1)
+ * @ingroup internal */
+
+/** @defgroup internalPGTStorage PGT storage
+ * @ingroup internalProxy */
+
+/** @defgroup internalPGTStorageDb PGT storage in a database
+ * @ingroup internalPGTStorage */
+
+/** @defgroup internalPGTStorageFile PGT storage on the filesystem
+ * @ingroup internalPGTStorage */
+
+/** @defgroup internalCallback Callback from the CAS server
+ * @ingroup internalProxy */
+
+/** @defgroup internalProxyServices Proxy other services
+ * @ingroup internalProxy */
+
+/** @defgroup internalService CAS client features (CAS 2.0, Proxied service)
+ * @ingroup internal */
+
+/** @defgroup internalConfig Configuration
+ * @ingroup internal */
+
+/** @defgroup internalBehave Internal behaviour of phpCAS
+ * @ingroup internalConfig */
+
+/** @defgroup internalOutput HTML output
+ * @ingroup internalConfig */
+
+/** @defgroup internalLang Internationalization
+ * @ingroup internalConfig
+ *
+ * To add a new language:
+ * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php
+ * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php
+ * - 3. Make the translations
+ */
+
+/** @defgroup internalDebug Debugging
+ * @ingroup internal */
+
+/** @defgroup internalMisc Miscellaneous
+ * @ingroup internal */
+
+// ########################################################################
+// EXAMPLES
+
+/**
+ * @example example_simple.php
+ */
+/**
+ * @example example_service.php
+ */
+/**
+ * @example example_service_that_proxies.php
+ */
+/**
+ * @example example_service_POST.php
+ */
+/**
+ * @example example_proxy_serviceWeb.php
+ */
+/**
+ * @example example_proxy_serviceWeb_chaining.php
+ */
+/**
+ * @example example_proxy_POST.php
+ */
+/**
+ * @example example_proxy_GET.php
+ */
+/**
+ * @example example_lang.php
+ */
+/**
+ * @example example_html.php
+ */
+/**
+ * @example example_pgt_storage_file.php
+ */
+/**
+ * @example example_pgt_storage_db.php
+ */
+/**
+ * @example example_gateway.php
+ */
+/**
+ * @example example_logout.php
+ */
+/**
+ * @example example_rebroadcast.php
+ */
+/**
+ * @example example_custom_urls.php
+ */
+/**
+ * @example example_advanced_saml11.php
+ */
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/AuthenticationException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines methods that allow proxy-authenticated service handlers
+ * to interact with phpCAS.
+ *
+ * Proxy service handlers must implement this interface as well as call
+ * phpCAS::initializeProxiedService($this) at some point in their implementation.
+ *
+ * While not required, proxy-authenticated service handlers are encouraged to
+ * implement the CAS_ProxiedService_Testable interface to facilitate unit testing.
+ *
+ * @class CAS_AuthenticationException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class CAS_AuthenticationException
+extends RuntimeException
+implements CAS_Exception
+{
+
+ /**
+ * This method is used to print the HTML output when the user was not
+ * authenticated.
+ *
+ * @param CAS_Client $client phpcas client
+ * @param string $failure the failure that occured
+ * @param string $cas_url the URL the CAS server was asked for
+ * @param bool $no_response the response from the CAS server (other
+ * parameters are ignored if TRUE)
+ * @param bool $bad_response bad response from the CAS server ($err_code
+ * and $err_msg ignored if TRUE)
+ * @param string $cas_response the response of the CAS server
+ * @param int $err_code the error code given by the CAS server
+ * @param string $err_msg the error message given by the CAS server
+ */
+ public function __construct($client,$failure,$cas_url,$no_response,
+ $bad_response=false,$cas_response='',$err_code=-1,$err_msg=''
+ ) {
+ $messages = array();
+ phpCAS::traceBegin();
+ $lang = $client->getLangObj();
+ $client->printHTMLHeader($lang->getAuthenticationFailed());
+ printf(
+ $lang->getYouWereNotAuthenticated(),
+ htmlentities($client->getURL()),
+ isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN']:''
+ );
+ phpCAS::trace($messages[] = 'CAS URL: '.$cas_url);
+ phpCAS::trace($messages[] = 'Authentication failure: '.$failure);
+ if ( $no_response ) {
+ phpCAS::trace($messages[] = 'Reason: no response from the CAS server');
+ } else {
+ if ( $bad_response ) {
+ phpCAS::trace($messages[] = 'Reason: bad response from the CAS server');
+ } else {
+ switch ($client->getServerVersion()) {
+ case CAS_VERSION_1_0:
+ phpCAS::trace($messages[] = 'Reason: CAS error');
+ break;
+ case CAS_VERSION_2_0:
+ case CAS_VERSION_3_0:
+ if ( $err_code === -1 ) {
+ phpCAS::trace($messages[] = 'Reason: no CAS error');
+ } else {
+ phpCAS::trace($messages[] = 'Reason: ['.$err_code.'] CAS error: '.$err_msg);
+ }
+ break;
+ }
+ }
+ phpCAS::trace($messages[] = 'CAS response: '.$cas_response);
+ }
+ $client->printHTMLFooter();
+ phpCAS::traceExit();
+
+ parent::__construct(implode("\n", $messages));
+ }
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Autoloader Class
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Autoload.php
+ * @category Authentication
+ * @package SimpleCAS
+ * @author Brett Bieber <brett.bieber@gmail.com>
+ * @copyright 2008 Regents of the University of Nebraska
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD License
+ * @link http://code.google.com/p/simplecas/
+ **/
+
+/**
+ * Autoload a class
+ *
+ * @param string $class Classname to load
+ *
+ * @return bool
+ */
+function CAS_autoload($class)
+{
+ // Static to hold the Include Path to CAS
+ static $include_path;
+ // Check only for CAS classes
+ if (substr($class, 0, 4) !== 'CAS_') {
+ return false;
+ }
+ // Setup the include path if it's not already set from a previous call
+ if (empty($include_path)) {
+ $include_path = array(dirname(dirname(__FILE__)), dirname(dirname(__FILE__)) . '/../test/' );
+ }
+
+ // Declare local variable to store the expected full path to the file
+
+ foreach ($include_path as $path) {
+ $file_path = $path . '/' . str_replace('_', '/', $class) . '.php';
+ $fp = @fopen($file_path, 'r', true);
+ if ($fp) {
+ fclose($fp);
+ include $file_path;
+ if (!class_exists($class, false) && !interface_exists($class, false)) {
+ die(
+ new Exception(
+ 'Class ' . $class . ' was not present in ' .
+ $file_path .
+ ' [CAS_autoload]'
+ )
+ );
+ }
+ return true;
+ }
+ }
+ $e = new Exception(
+ 'Class ' . $class . ' could not be loaded from ' .
+ $file_path . ', file does not exist (Path="'
+ . implode(':', $include_path) .'") [CAS_autoload]'
+ );
+ $trace = $e->getTrace();
+ if (isset($trace[2]) && isset($trace[2]['function'])
+ && in_array($trace[2]['function'], array('class_exists', 'interface_exists'))
+ ) {
+ return false;
+ }
+ if (isset($trace[1]) && isset($trace[1]['function'])
+ && in_array($trace[1]['function'], array('class_exists', 'interface_exists'))
+ ) {
+ return false;
+ }
+ die ((string) $e);
+}
+
+// set up __autoload
+if (!(spl_autoload_functions())
+ || !in_array('CAS_autoload', spl_autoload_functions())
+) {
+ spl_autoload_register('CAS_autoload');
+ if (function_exists('__autoload')
+ && !in_array('__autoload', spl_autoload_functions())
+ ) {
+ // __autoload() was being used, but now would be ignored, add
+ // it to the autoload stack
+ spl_autoload_register('__autoload');
+ }
+}
+
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Client.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author Brett Bieber <brett.bieber@gmail.com>
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * The CAS_Client class is a client interface that provides CAS authentication
+ * to PHP applications.
+ *
+ * @class CAS_Client
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author Brett Bieber <brett.bieber@gmail.com>
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ */
+
+class CAS_Client
+{
+
+ // ########################################################################
+ // HTML OUTPUT
+ // ########################################################################
+ /**
+ * @addtogroup internalOutput
+ * @{
+ */
+
+ /**
+ * This method filters a string by replacing special tokens by appropriate values
+ * and prints it. The corresponding tokens are taken into account:
+ * - __CAS_VERSION__
+ * - __PHPCAS_VERSION__
+ * - __SERVER_BASE_URL__
+ *
+ * Used by CAS_Client::PrintHTMLHeader() and CAS_Client::printHTMLFooter().
+ *
+ * @param string $str the string to filter and output
+ *
+ * @return void
+ */
+ private function _htmlFilterOutput($str)
+ {
+ $str = str_replace('__CAS_VERSION__', $this->getServerVersion(), $str);
+ $str = str_replace('__PHPCAS_VERSION__', phpCAS::getVersion(), $str);
+ $str = str_replace('__SERVER_BASE_URL__', $this->_getServerBaseURL(), $str);
+ echo $str;
+ }
+
+ /**
+ * A string used to print the header of HTML pages. Written by
+ * CAS_Client::setHTMLHeader(), read by CAS_Client::printHTMLHeader().
+ *
+ * @hideinitializer
+ * @see CAS_Client::setHTMLHeader, CAS_Client::printHTMLHeader()
+ */
+ private $_output_header = '';
+
+ /**
+ * This method prints the header of the HTML output (after filtering). If
+ * CAS_Client::setHTMLHeader() was not used, a default header is output.
+ *
+ * @param string $title the title of the page
+ *
+ * @return void
+ * @see _htmlFilterOutput()
+ */
+ public function printHTMLHeader($title)
+ {
+ $this->_htmlFilterOutput(
+ str_replace(
+ '__TITLE__', $title,
+ (empty($this->_output_header)
+ ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
+ : $this->_output_header)
+ )
+ );
+ }
+
+ /**
+ * A string used to print the footer of HTML pages. Written by
+ * CAS_Client::setHTMLFooter(), read by printHTMLFooter().
+ *
+ * @hideinitializer
+ * @see CAS_Client::setHTMLFooter, CAS_Client::printHTMLFooter()
+ */
+ private $_output_footer = '';
+
+ /**
+ * This method prints the footer of the HTML output (after filtering). If
+ * CAS_Client::setHTMLFooter() was not used, a default footer is output.
+ *
+ * @return void
+ * @see _htmlFilterOutput()
+ */
+ public function printHTMLFooter()
+ {
+ $lang = $this->getLangObj();
+ $this->_htmlFilterOutput(
+ empty($this->_output_footer)?
+ (phpCAS::getVerbose())?
+ '<hr><address>phpCAS __PHPCAS_VERSION__ '
+ .$lang->getUsingServer()
+ .' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>'
+ :'</body></html>'
+ :$this->_output_footer
+ );
+ }
+
+ /**
+ * This method set the HTML header used for all outputs.
+ *
+ * @param string $header the HTML header.
+ *
+ * @return void
+ */
+ public function setHTMLHeader($header)
+ {
+ // Argument Validation
+ if (gettype($header) != 'string')
+ throw new CAS_TypeMismatchException($header, '$header', 'string');
+
+ $this->_output_header = $header;
+ }
+
+ /**
+ * This method set the HTML footer used for all outputs.
+ *
+ * @param string $footer the HTML footer.
+ *
+ * @return void
+ */
+ public function setHTMLFooter($footer)
+ {
+ // Argument Validation
+ if (gettype($footer) != 'string')
+ throw new CAS_TypeMismatchException($footer, '$footer', 'string');
+
+ $this->_output_footer = $footer;
+ }
+
+
+ /** @} */
+
+
+ // ########################################################################
+ // INTERNATIONALIZATION
+ // ########################################################################
+ /**
+ * @addtogroup internalLang
+ * @{
+ */
+ /**
+ * A string corresponding to the language used by phpCAS. Written by
+ * CAS_Client::setLang(), read by CAS_Client::getLang().
+
+ * @note debugging information is always in english (debug purposes only).
+ */
+ private $_lang = PHPCAS_LANG_DEFAULT;
+
+ /**
+ * This method is used to set the language used by phpCAS.
+ *
+ * @param string $lang representing the language.
+ *
+ * @return void
+ */
+ public function setLang($lang)
+ {
+ // Argument Validation
+ if (gettype($lang) != 'string')
+ throw new CAS_TypeMismatchException($lang, '$lang', 'string');
+
+ phpCAS::traceBegin();
+ $obj = new $lang();
+ if (!($obj instanceof CAS_Languages_LanguageInterface)) {
+ throw new CAS_InvalidArgumentException(
+ '$className must implement the CAS_Languages_LanguageInterface'
+ );
+ }
+ $this->_lang = $lang;
+ phpCAS::traceEnd();
+ }
+ /**
+ * Create the language
+ *
+ * @return CAS_Languages_LanguageInterface object implementing the class
+ */
+ public function getLangObj()
+ {
+ $classname = $this->_lang;
+ return new $classname();
+ }
+
+ /** @} */
+ // ########################################################################
+ // CAS SERVER CONFIG
+ // ########################################################################
+ /**
+ * @addtogroup internalConfig
+ * @{
+ */
+
+ /**
+ * a record to store information about the CAS server.
+ * - $_server['version']: the version of the CAS server
+ * - $_server['hostname']: the hostname of the CAS server
+ * - $_server['port']: the port the CAS server is running on
+ * - $_server['uri']: the base URI the CAS server is responding on
+ * - $_server['base_url']: the base URL of the CAS server
+ * - $_server['login_url']: the login URL of the CAS server
+ * - $_server['service_validate_url']: the service validating URL of the
+ * CAS server
+ * - $_server['proxy_url']: the proxy URL of the CAS server
+ * - $_server['proxy_validate_url']: the proxy validating URL of the CAS server
+ * - $_server['logout_url']: the logout URL of the CAS server
+ *
+ * $_server['version'], $_server['hostname'], $_server['port'] and
+ * $_server['uri'] are written by CAS_Client::CAS_Client(), read by
+ * CAS_Client::getServerVersion(), CAS_Client::_getServerHostname(),
+ * CAS_Client::_getServerPort() and CAS_Client::_getServerURI().
+ *
+ * The other fields are written and read by CAS_Client::_getServerBaseURL(),
+ * CAS_Client::getServerLoginURL(), CAS_Client::getServerServiceValidateURL(),
+ * CAS_Client::getServerProxyValidateURL() and CAS_Client::getServerLogoutURL().
+ *
+ * @hideinitializer
+ */
+ private $_server = array(
+ 'version' => '',
+ 'hostname' => 'none',
+ 'port' => -1,
+ 'uri' => 'none');
+
+ /**
+ * This method is used to retrieve the version of the CAS server.
+ *
+ * @return string the version of the CAS server.
+ */
+ public function getServerVersion()
+ {
+ return $this->_server['version'];
+ }
+
+ /**
+ * This method is used to retrieve the hostname of the CAS server.
+ *
+ * @return string the hostname of the CAS server.
+ */
+ private function _getServerHostname()
+ {
+ return $this->_server['hostname'];
+ }
+
+ /**
+ * This method is used to retrieve the port of the CAS server.
+ *
+ * @return int the port of the CAS server.
+ */
+ private function _getServerPort()
+ {
+ return $this->_server['port'];
+ }
+
+ /**
+ * This method is used to retrieve the URI of the CAS server.
+ *
+ * @return string a URI.
+ */
+ private function _getServerURI()
+ {
+ return $this->_server['uri'];
+ }
+
+ /**
+ * This method is used to retrieve the base URL of the CAS server.
+ *
+ * @return string a URL.
+ */
+ private function _getServerBaseURL()
+ {
+ // the URL is build only when needed
+ if ( empty($this->_server['base_url']) ) {
+ $this->_server['base_url'] = 'https://' . $this->_getServerHostname();
+ if ($this->_getServerPort()!=443) {
+ $this->_server['base_url'] .= ':'
+ .$this->_getServerPort();
+ }
+ $this->_server['base_url'] .= $this->_getServerURI();
+ }
+ return $this->_server['base_url'];
+ }
+
+ /**
+ * This method is used to retrieve the login URL of the CAS server.
+ *
+ * @param bool $gateway true to check authentication, false to force it
+ * @param bool $renew true to force the authentication with the CAS server
+ *
+ * @return string a URL.
+ * @note It is recommended that CAS implementations ignore the "gateway"
+ * parameter if "renew" is set
+ */
+ public function getServerLoginURL($gateway=false,$renew=false)
+ {
+ phpCAS::traceBegin();
+ // the URL is build only when needed
+ if ( empty($this->_server['login_url']) ) {
+ $this->_server['login_url'] = $this->_buildQueryUrl($this->_getServerBaseURL().'login','service='.urlencode($this->getURL()));
+ }
+ $url = $this->_server['login_url'];
+ if ($renew) {
+ // It is recommended that when the "renew" parameter is set, its
+ // value be "true"
+ $url = $this->_buildQueryUrl($url, 'renew=true');
+ } elseif ($gateway) {
+ // It is recommended that when the "gateway" parameter is set, its
+ // value be "true"
+ $url = $this->_buildQueryUrl($url, 'gateway=true');
+ }
+ phpCAS::traceEnd($url);
+ return $url;
+ }
+
+ /**
+ * This method sets the login URL of the CAS server.
+ *
+ * @param string $url the login URL
+ *
+ * @return string login url
+ */
+ public function setServerLoginURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_server['login_url'] = $url;
+ }
+
+
+ /**
+ * This method sets the serviceValidate URL of the CAS server.
+ *
+ * @param string $url the serviceValidate URL
+ *
+ * @return string serviceValidate URL
+ */
+ public function setServerServiceValidateURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_server['service_validate_url'] = $url;
+ }
+
+
+ /**
+ * This method sets the proxyValidate URL of the CAS server.
+ *
+ * @param string $url the proxyValidate URL
+ *
+ * @return string proxyValidate URL
+ */
+ public function setServerProxyValidateURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_server['proxy_validate_url'] = $url;
+ }
+
+
+ /**
+ * This method sets the samlValidate URL of the CAS server.
+ *
+ * @param string $url the samlValidate URL
+ *
+ * @return string samlValidate URL
+ */
+ public function setServerSamlValidateURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_server['saml_validate_url'] = $url;
+ }
+
+
+ /**
+ * This method is used to retrieve the service validating URL of the CAS server.
+ *
+ * @return string serviceValidate URL.
+ */
+ public function getServerServiceValidateURL()
+ {
+ phpCAS::traceBegin();
+ // the URL is build only when needed
+ if ( empty($this->_server['service_validate_url']) ) {
+ switch ($this->getServerVersion()) {
+ case CAS_VERSION_1_0:
+ $this->_server['service_validate_url'] = $this->_getServerBaseURL()
+ .'validate';
+ break;
+ case CAS_VERSION_2_0:
+ $this->_server['service_validate_url'] = $this->_getServerBaseURL()
+ .'serviceValidate';
+ break;
+ case CAS_VERSION_3_0:
+ $this->_server['service_validate_url'] = $this->_getServerBaseURL()
+ .'p3/serviceValidate';
+ break;
+ }
+ }
+ $url = $this->_buildQueryUrl(
+ $this->_server['service_validate_url'],
+ 'service='.urlencode($this->getURL())
+ );
+ phpCAS::traceEnd($url);
+ return $url;
+ }
+ /**
+ * This method is used to retrieve the SAML validating URL of the CAS server.
+ *
+ * @return string samlValidate URL.
+ */
+ public function getServerSamlValidateURL()
+ {
+ phpCAS::traceBegin();
+ // the URL is build only when needed
+ if ( empty($this->_server['saml_validate_url']) ) {
+ switch ($this->getServerVersion()) {
+ case SAML_VERSION_1_1:
+ $this->_server['saml_validate_url'] = $this->_getServerBaseURL().'samlValidate';
+ break;
+ }
+ }
+
+ $url = $this->_buildQueryUrl(
+ $this->_server['saml_validate_url'],
+ 'TARGET='.urlencode($this->getURL())
+ );
+ phpCAS::traceEnd($url);
+ return $url;
+ }
+
+ /**
+ * This method is used to retrieve the proxy validating URL of the CAS server.
+ *
+ * @return string proxyValidate URL.
+ */
+ public function getServerProxyValidateURL()
+ {
+ phpCAS::traceBegin();
+ // the URL is build only when needed
+ if ( empty($this->_server['proxy_validate_url']) ) {
+ switch ($this->getServerVersion()) {
+ case CAS_VERSION_1_0:
+ $this->_server['proxy_validate_url'] = '';
+ break;
+ case CAS_VERSION_2_0:
+ $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'proxyValidate';
+ break;
+ case CAS_VERSION_3_0:
+ $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'p3/proxyValidate';
+ break;
+ }
+ }
+ $url = $this->_buildQueryUrl(
+ $this->_server['proxy_validate_url'],
+ 'service='.urlencode($this->getURL())
+ );
+ phpCAS::traceEnd($url);
+ return $url;
+ }
+
+
+ /**
+ * This method is used to retrieve the proxy URL of the CAS server.
+ *
+ * @return string proxy URL.
+ */
+ public function getServerProxyURL()
+ {
+ // the URL is build only when needed
+ if ( empty($this->_server['proxy_url']) ) {
+ switch ($this->getServerVersion()) {
+ case CAS_VERSION_1_0:
+ $this->_server['proxy_url'] = '';
+ break;
+ case CAS_VERSION_2_0:
+ case CAS_VERSION_3_0:
+ $this->_server['proxy_url'] = $this->_getServerBaseURL().'proxy';
+ break;
+ }
+ }
+ return $this->_server['proxy_url'];
+ }
+
+ /**
+ * This method is used to retrieve the logout URL of the CAS server.
+ *
+ * @return string logout URL.
+ */
+ public function getServerLogoutURL()
+ {
+ // the URL is build only when needed
+ if ( empty($this->_server['logout_url']) ) {
+ $this->_server['logout_url'] = $this->_getServerBaseURL().'logout';
+ }
+ return $this->_server['logout_url'];
+ }
+
+ /**
+ * This method sets the logout URL of the CAS server.
+ *
+ * @param string $url the logout URL
+ *
+ * @return string logout url
+ */
+ public function setServerLogoutURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_server['logout_url'] = $url;
+ }
+
+ /**
+ * An array to store extra curl options.
+ */
+ private $_curl_options = array();
+
+ /**
+ * This method is used to set additional user curl options.
+ *
+ * @param string $key name of the curl option
+ * @param string $value value of the curl option
+ *
+ * @return void
+ */
+ public function setExtraCurlOption($key, $value)
+ {
+ $this->_curl_options[$key] = $value;
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // Change the internal behaviour of phpcas
+ // ########################################################################
+
+ /**
+ * @addtogroup internalBehave
+ * @{
+ */
+
+ /**
+ * The class to instantiate for making web requests in readUrl().
+ * The class specified must implement the CAS_Request_RequestInterface.
+ * By default CAS_Request_CurlRequest is used, but this may be overridden to
+ * supply alternate request mechanisms for testing.
+ */
+ private $_requestImplementation = 'CAS_Request_CurlRequest';
+
+ /**
+ * Override the default implementation used to make web requests in readUrl().
+ * This class must implement the CAS_Request_RequestInterface.
+ *
+ * @param string $className name of the RequestImplementation class
+ *
+ * @return void
+ */
+ public function setRequestImplementation ($className)
+ {
+ $obj = new $className;
+ if (!($obj instanceof CAS_Request_RequestInterface)) {
+ throw new CAS_InvalidArgumentException(
+ '$className must implement the CAS_Request_RequestInterface'
+ );
+ }
+ $this->_requestImplementation = $className;
+ }
+
+ /**
+ * @var boolean $_clearTicketsFromUrl; If true, phpCAS will clear session
+ * tickets from the URL after a successful authentication.
+ */
+ private $_clearTicketsFromUrl = true;
+
+ /**
+ * Configure the client to not send redirect headers and call exit() on
+ * authentication success. The normal redirect is used to remove the service
+ * ticket from the client's URL, but for running unit tests we need to
+ * continue without exiting.
+ *
+ * Needed for testing authentication
+ *
+ * @return void
+ */
+ public function setNoClearTicketsFromUrl ()
+ {
+ $this->_clearTicketsFromUrl = false;
+ }
+
+ /**
+ * @var callback $_attributeParserCallbackFunction;
+ */
+ private $_casAttributeParserCallbackFunction = null;
+
+ /**
+ * @var array $_attributeParserCallbackArgs;
+ */
+ private $_casAttributeParserCallbackArgs = array();
+
+ /**
+ * Set a callback function to be run when parsing CAS attributes
+ *
+ * The callback function will be passed a XMLNode as its first parameter,
+ * followed by any $additionalArgs you pass.
+ *
+ * @param string $function callback function to call
+ * @param array $additionalArgs optional array of arguments
+ *
+ * @return void
+ */
+ public function setCasAttributeParserCallback($function, array $additionalArgs = array())
+ {
+ $this->_casAttributeParserCallbackFunction = $function;
+ $this->_casAttributeParserCallbackArgs = $additionalArgs;
+ }
+
+ /** @var callable $_postAuthenticateCallbackFunction;
+ */
+ private $_postAuthenticateCallbackFunction = null;
+
+ /**
+ * @var array $_postAuthenticateCallbackArgs;
+ */
+ private $_postAuthenticateCallbackArgs = array();
+
+ /**
+ * Set a callback function to be run when a user authenticates.
+ *
+ * The callback function will be passed a $logoutTicket as its first parameter,
+ * followed by any $additionalArgs you pass. The $logoutTicket parameter is an
+ * opaque string that can be used to map a session-id to the logout request
+ * in order to support single-signout in applications that manage their own
+ * sessions (rather than letting phpCAS start the session).
+ *
+ * phpCAS::forceAuthentication() will always exit and forward client unless
+ * they are already authenticated. To perform an action at the moment the user
+ * logs in (such as registering an account, performing logging, etc), register
+ * a callback function here.
+ *
+ * @param callable $function callback function to call
+ * @param array $additionalArgs optional array of arguments
+ *
+ * @return void
+ */
+ public function setPostAuthenticateCallback ($function, array $additionalArgs = array())
+ {
+ $this->_postAuthenticateCallbackFunction = $function;
+ $this->_postAuthenticateCallbackArgs = $additionalArgs;
+ }
+
+ /**
+ * @var callable $_signoutCallbackFunction;
+ */
+ private $_signoutCallbackFunction = null;
+
+ /**
+ * @var array $_signoutCallbackArgs;
+ */
+ private $_signoutCallbackArgs = array();
+
+ /**
+ * Set a callback function to be run when a single-signout request is received.
+ *
+ * The callback function will be passed a $logoutTicket as its first parameter,
+ * followed by any $additionalArgs you pass. The $logoutTicket parameter is an
+ * opaque string that can be used to map a session-id to the logout request in
+ * order to support single-signout in applications that manage their own sessions
+ * (rather than letting phpCAS start and destroy the session).
+ *
+ * @param callable $function callback function to call
+ * @param array $additionalArgs optional array of arguments
+ *
+ * @return void
+ */
+ public function setSingleSignoutCallback ($function, array $additionalArgs = array())
+ {
+ $this->_signoutCallbackFunction = $function;
+ $this->_signoutCallbackArgs = $additionalArgs;
+ }
+
+ // ########################################################################
+ // Methods for supplying code-flow feedback to integrators.
+ // ########################################################################
+
+ /**
+ * Ensure that this is actually a proxy object or fail with an exception
+ *
+ * @throws CAS_OutOfSequenceBeforeProxyException
+ *
+ * @return void
+ */
+ public function ensureIsProxy()
+ {
+ if (!$this->isProxy()) {
+ throw new CAS_OutOfSequenceBeforeProxyException();
+ }
+ }
+
+ /**
+ * Mark the caller of authentication. This will help client integraters determine
+ * problems with their code flow if they call a function such as getUser() before
+ * authentication has occurred.
+ *
+ * @param bool $auth True if authentication was successful, false otherwise.
+ *
+ * @return null
+ */
+ public function markAuthenticationCall ($auth)
+ {
+ // store where the authentication has been checked and the result
+ $dbg = debug_backtrace();
+ $this->_authentication_caller = array (
+ 'file' => $dbg[1]['file'],
+ 'line' => $dbg[1]['line'],
+ 'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'],
+ 'result' => (boolean)$auth
+ );
+ }
+ private $_authentication_caller;
+
+ /**
+ * Answer true if authentication has been checked.
+ *
+ * @return bool
+ */
+ public function wasAuthenticationCalled ()
+ {
+ return !empty($this->_authentication_caller);
+ }
+
+ /**
+ * Ensure that authentication was checked. Terminate with exception if no
+ * authentication was performed
+ *
+ * @throws CAS_OutOfSequenceBeforeAuthenticationCallException
+ *
+ * @return void
+ */
+ private function _ensureAuthenticationCalled()
+ {
+ if (!$this->wasAuthenticationCalled()) {
+ throw new CAS_OutOfSequenceBeforeAuthenticationCallException();
+ }
+ }
+
+ /**
+ * Answer the result of the authentication call.
+ *
+ * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+ * and markAuthenticationCall() didn't happen.
+ *
+ * @return bool
+ */
+ public function wasAuthenticationCallSuccessful ()
+ {
+ $this->_ensureAuthenticationCalled();
+ return $this->_authentication_caller['result'];
+ }
+
+
+ /**
+ * Ensure that authentication was checked. Terminate with exception if no
+ * authentication was performed
+ *
+ * @throws CAS_OutOfSequenceException
+ *
+ * @return void
+ */
+ public function ensureAuthenticationCallSuccessful()
+ {
+ $this->_ensureAuthenticationCalled();
+ if (!$this->_authentication_caller['result']) {
+ throw new CAS_OutOfSequenceException(
+ 'authentication was checked (by '
+ . $this->getAuthenticationCallerMethod()
+ . '() at ' . $this->getAuthenticationCallerFile()
+ . ':' . $this->getAuthenticationCallerLine()
+ . ') but the method returned false'
+ );
+ }
+ }
+
+ /**
+ * Answer information about the authentication caller.
+ *
+ * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+ * and markAuthenticationCall() didn't happen.
+ *
+ * @return string the file that called authentication
+ */
+ public function getAuthenticationCallerFile ()
+ {
+ $this->_ensureAuthenticationCalled();
+ return $this->_authentication_caller['file'];
+ }
+
+ /**
+ * Answer information about the authentication caller.
+ *
+ * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+ * and markAuthenticationCall() didn't happen.
+ *
+ * @return int the line that called authentication
+ */
+ public function getAuthenticationCallerLine ()
+ {
+ $this->_ensureAuthenticationCalled();
+ return $this->_authentication_caller['line'];
+ }
+
+ /**
+ * Answer information about the authentication caller.
+ *
+ * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+ * and markAuthenticationCall() didn't happen.
+ *
+ * @return string the method that called authentication
+ */
+ public function getAuthenticationCallerMethod ()
+ {
+ $this->_ensureAuthenticationCalled();
+ return $this->_authentication_caller['method'];
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+ /**
+ * @addtogroup internalConfig
+ * @{
+ */
+
+ /**
+ * CAS_Client constructor.
+ *
+ * @param string $server_version the version of the CAS server
+ * @param bool $proxy true if the CAS client is a CAS proxy
+ * @param string $server_hostname the hostname of the CAS server
+ * @param int $server_port the port the CAS server is running on
+ * @param string $server_uri the URI the CAS server is responding on
+ * @param bool $changeSessionID Allow phpCAS to change the session_id
+ * (Single Sign Out/handleLogoutRequests
+ * is based on that change)
+ *
+ * @return self a newly created CAS_Client object
+ */
+ public function __construct(
+ $server_version,
+ $proxy,
+ $server_hostname,
+ $server_port,
+ $server_uri,
+ $changeSessionID = true
+ ) {
+ // Argument validation
+ if (gettype($server_version) != 'string')
+ throw new CAS_TypeMismatchException($server_version, '$server_version', 'string');
+ if (gettype($proxy) != 'boolean')
+ throw new CAS_TypeMismatchException($proxy, '$proxy', 'boolean');
+ if (gettype($server_hostname) != 'string')
+ throw new CAS_TypeMismatchException($server_hostname, '$server_hostname', 'string');
+ if (gettype($server_port) != 'integer')
+ throw new CAS_TypeMismatchException($server_port, '$server_port', 'integer');
+ if (gettype($server_uri) != 'string')
+ throw new CAS_TypeMismatchException($server_uri, '$server_uri', 'string');
+ if (gettype($changeSessionID) != 'boolean')
+ throw new CAS_TypeMismatchException($changeSessionID, '$changeSessionID', 'boolean');
+
+ phpCAS::traceBegin();
+ // true : allow to change the session_id(), false session_id won't be
+ // change and logout won't be handle because of that
+ $this->_setChangeSessionID($changeSessionID);
+
+ // skip Session Handling for logout requests and if don't want it'
+ if (session_id()=="" && !$this->_isLogoutRequest()) {
+ session_start();
+ phpCAS :: trace("Starting a new session " . session_id());
+ }
+ // Only for debug purposes
+ if ($this->isSessionAuthenticated()){
+ phpCAS :: trace("Session is authenticated as: " . $_SESSION['phpCAS']['user']);
+ } else {
+ phpCAS :: trace("Session is not authenticated");
+ }
+ // are we in proxy mode ?
+ $this->_proxy = $proxy;
+
+ // Make cookie handling available.
+ if ($this->isProxy()) {
+ if (!isset($_SESSION['phpCAS'])) {
+ $_SESSION['phpCAS'] = array();
+ }
+ if (!isset($_SESSION['phpCAS']['service_cookies'])) {
+ $_SESSION['phpCAS']['service_cookies'] = array();
+ }
+ $this->_serviceCookieJar = new CAS_CookieJar(
+ $_SESSION['phpCAS']['service_cookies']
+ );
+ }
+
+ // check version
+ $supportedProtocols = phpCAS::getSupportedProtocols();
+ if (isset($supportedProtocols[$server_version]) === false) {
+ phpCAS::error(
+ 'this version of CAS (`'.$server_version
+ .'\') is not supported by phpCAS '.phpCAS::getVersion()
+ );
+ }
+
+ if ($server_version === CAS_VERSION_1_0 && $this->isProxy()) {
+ phpCAS::error(
+ 'CAS proxies are not supported in CAS '.$server_version
+ );
+ }
+
+ $this->_server['version'] = $server_version;
+
+ // check hostname
+ if ( empty($server_hostname)
+ || !preg_match('/[\.\d\-a-z]*/', $server_hostname)
+ ) {
+ phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
+ }
+ $this->_server['hostname'] = $server_hostname;
+
+ // check port
+ if ( $server_port == 0
+ || !is_int($server_port)
+ ) {
+ phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
+ }
+ $this->_server['port'] = $server_port;
+
+ // check URI
+ if ( !preg_match('/[\.\d\-_a-z\/]*/', $server_uri) ) {
+ phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
+ }
+ // add leading and trailing `/' and remove doubles
+ if(strstr($server_uri, '?') === false) $server_uri .= '/';
+ $server_uri = preg_replace('/\/\//', '/', '/'.$server_uri);
+ $this->_server['uri'] = $server_uri;
+
+ // set to callback mode if PgtIou and PgtId CGI GET parameters are provided
+ if ( $this->isProxy() ) {
+ $this->_setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
+ }
+
+ if ( $this->_isCallbackMode() ) {
+ //callback mode: check that phpCAS is secured
+ if ( !$this->_isHttps() ) {
+ phpCAS::error(
+ 'CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server'
+ );
+ }
+ } else {
+ //normal mode: get ticket and remove it from CGI parameters for
+ // developers
+ $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
+ if (preg_match('/^[SP]T-/', $ticket) ) {
+ phpCAS::trace('Ticket \''.$ticket.'\' found');
+ $this->setTicket($ticket);
+ unset($_GET['ticket']);
+ } else if ( !empty($ticket) ) {
+ //ill-formed ticket, halt
+ phpCAS::error(
+ 'ill-formed ticket found in the URL (ticket=`'
+ .htmlentities($ticket).'\')'
+ );
+ }
+
+ }
+ phpCAS::traceEnd();
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX Session Handling XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ /**
+ * @addtogroup internalConfig
+ * @{
+ */
+
+
+ /**
+ * @var bool A variable to whether phpcas will use its own session handling. Default = true
+ * @hideinitializer
+ */
+ private $_change_session_id = true;
+
+ /**
+ * Set a parameter whether to allow phpCAS to change session_id
+ *
+ * @param bool $allowed allow phpCAS to change session_id
+ *
+ * @return void
+ */
+ private function _setChangeSessionID($allowed)
+ {
+ $this->_change_session_id = $allowed;
+ }
+
+ /**
+ * Get whether phpCAS is allowed to change session_id
+ *
+ * @return bool
+ */
+ public function getChangeSessionID()
+ {
+ return $this->_change_session_id;
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX AUTHENTICATION XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ /**
+ * @addtogroup internalAuthentication
+ * @{
+ */
+
+ /**
+ * The Authenticated user. Written by CAS_Client::_setUser(), read by
+ * CAS_Client::getUser().
+ *
+ * @hideinitializer
+ */
+ private $_user = '';
+
+ /**
+ * This method sets the CAS user's login name.
+ *
+ * @param string $user the login name of the authenticated user.
+ *
+ * @return void
+ */
+ private function _setUser($user)
+ {
+ $this->_user = $user;
+ }
+
+ /**
+ * This method returns the CAS user's login name.
+ *
+ * @return string the login name of the authenticated user
+ *
+ * @warning should be called only after CAS_Client::forceAuthentication() or
+ * CAS_Client::isAuthenticated(), otherwise halt with an error.
+ */
+ public function getUser()
+ {
+ // Sequence validation
+ $this->ensureAuthenticationCallSuccessful();
+
+ return $this->_getUser();
+ }
+
+ /**
+ * This method returns the CAS user's login name.
+ *
+ * @return string the login name of the authenticated user
+ *
+ * @warning should be called only after CAS_Client::forceAuthentication() or
+ * CAS_Client::isAuthenticated(), otherwise halt with an error.
+ */
+ private function _getUser()
+ {
+ // This is likely a duplicate check that could be removed....
+ if ( empty($this->_user) ) {
+ phpCAS::error(
+ 'this method should be used only after '.__CLASS__
+ .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
+ );
+ }
+ return $this->_user;
+ }
+
+ /**
+ * The Authenticated users attributes. Written by
+ * CAS_Client::setAttributes(), read by CAS_Client::getAttributes().
+ * @attention client applications should use phpCAS::getAttributes().
+ *
+ * @hideinitializer
+ */
+ private $_attributes = array();
+
+ /**
+ * Set an array of attributes
+ *
+ * @param array $attributes a key value array of attributes
+ *
+ * @return void
+ */
+ public function setAttributes($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+
+ /**
+ * Get an key values arry of attributes
+ *
+ * @return array of attributes
+ */
+ public function getAttributes()
+ {
+ // Sequence validation
+ $this->ensureAuthenticationCallSuccessful();
+ // This is likely a duplicate check that could be removed....
+ if ( empty($this->_user) ) {
+ // if no user is set, there shouldn't be any attributes also...
+ phpCAS::error(
+ 'this method should be used only after '.__CLASS__
+ .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
+ );
+ }
+ return $this->_attributes;
+ }
+
+ /**
+ * Check whether attributes are available
+ *
+ * @return bool attributes available
+ */
+ public function hasAttributes()
+ {
+ // Sequence validation
+ $this->ensureAuthenticationCallSuccessful();
+
+ return !empty($this->_attributes);
+ }
+ /**
+ * Check whether a specific attribute with a name is available
+ *
+ * @param string $key name of attribute
+ *
+ * @return bool is attribute available
+ */
+ public function hasAttribute($key)
+ {
+ // Sequence validation
+ $this->ensureAuthenticationCallSuccessful();
+
+ return $this->_hasAttribute($key);
+ }
+
+ /**
+ * Check whether a specific attribute with a name is available
+ *
+ * @param string $key name of attribute
+ *
+ * @return bool is attribute available
+ */
+ private function _hasAttribute($key)
+ {
+ return (is_array($this->_attributes)
+ && array_key_exists($key, $this->_attributes));
+ }
+
+ /**
+ * Get a specific attribute by name
+ *
+ * @param string $key name of attribute
+ *
+ * @return string attribute values
+ */
+ public function getAttribute($key)
+ {
+ // Sequence validation
+ $this->ensureAuthenticationCallSuccessful();
+
+ if ($this->_hasAttribute($key)) {
+ return $this->_attributes[$key];
+ }
+ }
+
+ /**
+ * This method is called to renew the authentication of the user
+ * If the user is authenticated, renew the connection
+ * If not, redirect to CAS
+ *
+ * @return bool true when the user is authenticated; otherwise halt.
+ */
+ public function renewAuthentication()
+ {
+ phpCAS::traceBegin();
+ // Either way, the user is authenticated by CAS
+ if (isset( $_SESSION['phpCAS']['auth_checked'])) {
+ unset($_SESSION['phpCAS']['auth_checked']);
+ }
+ if ( $this->isAuthenticated(true) ) {
+ phpCAS::trace('user already authenticated');
+ $res = true;
+ } else {
+ $this->redirectToCas(false, true);
+ // never reached
+ $res = false;
+ }
+ phpCAS::traceEnd();
+ return $res;
+ }
+
+ /**
+ * This method is called to be sure that the user is authenticated. When not
+ * authenticated, halt by redirecting to the CAS server; otherwise return true.
+ *
+ * @return bool true when the user is authenticated; otherwise halt.
+ */
+ public function forceAuthentication()
+ {
+ phpCAS::traceBegin();
+
+ if ( $this->isAuthenticated() ) {
+ // the user is authenticated, nothing to be done.
+ phpCAS::trace('no need to authenticate');
+ $res = true;
+ } else {
+ // the user is not authenticated, redirect to the CAS server
+ if (isset($_SESSION['phpCAS']['auth_checked'])) {
+ unset($_SESSION['phpCAS']['auth_checked']);
+ }
+ $this->redirectToCas(false/* no gateway */);
+ // never reached
+ $res = false;
+ }
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+
+ /**
+ * An integer that gives the number of times authentication will be cached
+ * before rechecked.
+ *
+ * @hideinitializer
+ */
+ private $_cache_times_for_auth_recheck = 0;
+
+ /**
+ * Set the number of times authentication will be cached before rechecked.
+ *
+ * @param int $n number of times to wait for a recheck
+ *
+ * @return void
+ */
+ public function setCacheTimesForAuthRecheck($n)
+ {
+ if (gettype($n) != 'integer')
+ throw new CAS_TypeMismatchException($n, '$n', 'string');
+
+ $this->_cache_times_for_auth_recheck = $n;
+ }
+
+ /**
+ * This method is called to check whether the user is authenticated or not.
+ *
+ * @return bool true when the user is authenticated, false when a previous
+ * gateway login failed or the function will not return if the user is
+ * redirected to the cas server for a gateway login attempt
+ */
+ public function checkAuthentication()
+ {
+ phpCAS::traceBegin();
+ if ( $this->isAuthenticated() ) {
+ phpCAS::trace('user is authenticated');
+ /* The 'auth_checked' variable is removed just in case it's set. */
+ unset($_SESSION['phpCAS']['auth_checked']);
+ $res = true;
+ } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
+ // the previous request has redirected the client to the CAS server
+ // with gateway=true
+ unset($_SESSION['phpCAS']['auth_checked']);
+ $res = false;
+ } else {
+ // avoid a check against CAS on every request
+ if (!isset($_SESSION['phpCAS']['unauth_count'])) {
+ $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
+ }
+
+ if (($_SESSION['phpCAS']['unauth_count'] != -2
+ && $this->_cache_times_for_auth_recheck == -1)
+ || ($_SESSION['phpCAS']['unauth_count'] >= 0
+ && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck)
+ ) {
+ $res = false;
+
+ if ($this->_cache_times_for_auth_recheck != -1) {
+ $_SESSION['phpCAS']['unauth_count']++;
+ phpCAS::trace(
+ 'user is not authenticated (cached for '
+ .$_SESSION['phpCAS']['unauth_count'].' times of '
+ .$this->_cache_times_for_auth_recheck.')'
+ );
+ } else {
+ phpCAS::trace(
+ 'user is not authenticated (cached for until login pressed)'
+ );
+ }
+ } else {
+ $_SESSION['phpCAS']['unauth_count'] = 0;
+ $_SESSION['phpCAS']['auth_checked'] = true;
+ phpCAS::trace('user is not authenticated (cache reset)');
+ $this->redirectToCas(true/* gateway */);
+ // never reached
+ $res = false;
+ }
+ }
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+
+ /**
+ * This method is called to check if the user is authenticated (previously or by
+ * tickets given in the URL).
+ *
+ * @param bool $renew true to force the authentication with the CAS server
+ *
+ * @return bool true when the user is authenticated. Also may redirect to the
+ * same URL without the ticket.
+ */
+ public function isAuthenticated($renew=false)
+ {
+ phpCAS::traceBegin();
+ $res = false;
+ $validate_url = '';
+ if ( $this->_wasPreviouslyAuthenticated() ) {
+ if ($this->hasTicket()) {
+ // User has a additional ticket but was already authenticated
+ phpCAS::trace(
+ 'ticket was present and will be discarded, use renewAuthenticate()'
+ );
+ if ($this->_clearTicketsFromUrl) {
+ phpCAS::trace("Prepare redirect to : ".$this->getURL());
+ session_write_close();
+ header('Location: '.$this->getURL());
+ flush();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+ } else {
+ phpCAS::trace(
+ 'Already authenticated, but skipping ticket clearing since setNoClearTicketsFromUrl() was used.'
+ );
+ $res = true;
+ }
+ } else {
+ // the user has already (previously during the session) been
+ // authenticated, nothing to be done.
+ phpCAS::trace(
+ 'user was already authenticated, no need to look for tickets'
+ );
+ $res = true;
+ }
+
+ // Mark the auth-check as complete to allow post-authentication
+ // callbacks to make use of phpCAS::getUser() and similar methods
+ $this->markAuthenticationCall($res);
+ } else {
+ if ($this->hasTicket()) {
+ switch ($this->getServerVersion()) {
+ case CAS_VERSION_1_0:
+ // if a Service Ticket was given, validate it
+ phpCAS::trace(
+ 'CAS 1.0 ticket `'.$this->getTicket().'\' is present'
+ );
+ $this->validateCAS10(
+ $validate_url, $text_response, $tree_response, $renew
+ ); // if it fails, it halts
+ phpCAS::trace(
+ 'CAS 1.0 ticket `'.$this->getTicket().'\' was validated'
+ );
+ $_SESSION['phpCAS']['user'] = $this->_getUser();
+ $res = true;
+ $logoutTicket = $this->getTicket();
+ break;
+ case CAS_VERSION_2_0:
+ case CAS_VERSION_3_0:
+ // if a Proxy Ticket was given, validate it
+ phpCAS::trace(
+ 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' is present'
+ );
+ $this->validateCAS20(
+ $validate_url, $text_response, $tree_response, $renew
+ ); // note: if it fails, it halts
+ phpCAS::trace(
+ 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' was validated'
+ );
+ if ( $this->isProxy() ) {
+ $this->_validatePGT(
+ $validate_url, $text_response, $tree_response
+ ); // idem
+ phpCAS::trace('PGT `'.$this->_getPGT().'\' was validated');
+ $_SESSION['phpCAS']['pgt'] = $this->_getPGT();
+ }
+ $_SESSION['phpCAS']['user'] = $this->_getUser();
+ if (!empty($this->_attributes)) {
+ $_SESSION['phpCAS']['attributes'] = $this->_attributes;
+ }
+ $proxies = $this->getProxies();
+ if (!empty($proxies)) {
+ $_SESSION['phpCAS']['proxies'] = $this->getProxies();
+ }
+ $res = true;
+ $logoutTicket = $this->getTicket();
+ break;
+ case SAML_VERSION_1_1:
+ // if we have a SAML ticket, validate it.
+ phpCAS::trace(
+ 'SAML 1.1 ticket `'.$this->getTicket().'\' is present'
+ );
+ $this->validateSA(
+ $validate_url, $text_response, $tree_response, $renew
+ ); // if it fails, it halts
+ phpCAS::trace(
+ 'SAML 1.1 ticket `'.$this->getTicket().'\' was validated'
+ );
+ $_SESSION['phpCAS']['user'] = $this->_getUser();
+ $_SESSION['phpCAS']['attributes'] = $this->_attributes;
+ $res = true;
+ $logoutTicket = $this->getTicket();
+ break;
+ default:
+ phpCAS::trace('Protocoll error');
+ break;
+ }
+ } else {
+ // no ticket given, not authenticated
+ phpCAS::trace('no ticket found');
+ }
+
+ // Mark the auth-check as complete to allow post-authentication
+ // callbacks to make use of phpCAS::getUser() and similar methods
+ $this->markAuthenticationCall($res);
+
+ if ($res) {
+ // call the post-authenticate callback if registered.
+ if ($this->_postAuthenticateCallbackFunction) {
+ $args = $this->_postAuthenticateCallbackArgs;
+ array_unshift($args, $logoutTicket);
+ call_user_func_array(
+ $this->_postAuthenticateCallbackFunction, $args
+ );
+ }
+
+ // if called with a ticket parameter, we need to redirect to the
+ // app without the ticket so that CAS-ification is transparent
+ // to the browser (for later POSTS) most of the checks and
+ // errors should have been made now, so we're safe for redirect
+ // without masking error messages. remove the ticket as a
+ // security precaution to prevent a ticket in the HTTP_REFERRER
+ if ($this->_clearTicketsFromUrl) {
+ phpCAS::trace("Prepare redirect to : ".$this->getURL());
+ session_write_close();
+ header('Location: '.$this->getURL());
+ flush();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+ }
+ }
+ }
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+
+ /**
+ * This method tells if the current session is authenticated.
+ *
+ * @return bool true if authenticated based soley on $_SESSION variable
+ */
+ public function isSessionAuthenticated ()
+ {
+ return !empty($_SESSION['phpCAS']['user']);
+ }
+
+ /**
+ * This method tells if the user has already been (previously) authenticated
+ * by looking into the session variables.
+ *
+ * @note This function switches to callback mode when needed.
+ *
+ * @return bool true when the user has already been authenticated; false otherwise.
+ */
+ private function _wasPreviouslyAuthenticated()
+ {
+ phpCAS::traceBegin();
+
+ if ( $this->_isCallbackMode() ) {
+ // Rebroadcast the pgtIou and pgtId to all nodes
+ if ($this->_rebroadcast&&!isset($_POST['rebroadcast'])) {
+ $this->_rebroadcast(self::PGTIOU);
+ }
+ $this->_callback();
+ }
+
+ $auth = false;
+
+ if ( $this->isProxy() ) {
+ // CAS proxy: username and PGT must be present
+ if ( $this->isSessionAuthenticated()
+ && !empty($_SESSION['phpCAS']['pgt'])
+ ) {
+ // authentication already done
+ $this->_setUser($_SESSION['phpCAS']['user']);
+ if (isset($_SESSION['phpCAS']['attributes'])) {
+ $this->setAttributes($_SESSION['phpCAS']['attributes']);
+ }
+ $this->_setPGT($_SESSION['phpCAS']['pgt']);
+ phpCAS::trace(
+ 'user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'
+ .$_SESSION['phpCAS']['pgt'].'\''
+ );
+
+ // Include the list of proxies
+ if (isset($_SESSION['phpCAS']['proxies'])) {
+ $this->_setProxies($_SESSION['phpCAS']['proxies']);
+ phpCAS::trace(
+ 'proxies = "'
+ .implode('", "', $_SESSION['phpCAS']['proxies']).'"'
+ );
+ }
+
+ $auth = true;
+ } elseif ( $this->isSessionAuthenticated()
+ && empty($_SESSION['phpCAS']['pgt'])
+ ) {
+ // these two variables should be empty or not empty at the same time
+ phpCAS::trace(
+ 'username found (`'.$_SESSION['phpCAS']['user']
+ .'\') but PGT is empty'
+ );
+ // unset all tickets to enforce authentication
+ unset($_SESSION['phpCAS']);
+ $this->setTicket('');
+ } elseif ( !$this->isSessionAuthenticated()
+ && !empty($_SESSION['phpCAS']['pgt'])
+ ) {
+ // these two variables should be empty or not empty at the same time
+ phpCAS::trace(
+ 'PGT found (`'.$_SESSION['phpCAS']['pgt']
+ .'\') but username is empty'
+ );
+ // unset all tickets to enforce authentication
+ unset($_SESSION['phpCAS']);
+ $this->setTicket('');
+ } else {
+ phpCAS::trace('neither user nor PGT found');
+ }
+ } else {
+ // `simple' CAS client (not a proxy): username must be present
+ if ( $this->isSessionAuthenticated() ) {
+ // authentication already done
+ $this->_setUser($_SESSION['phpCAS']['user']);
+ if (isset($_SESSION['phpCAS']['attributes'])) {
+ $this->setAttributes($_SESSION['phpCAS']['attributes']);
+ }
+ phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\'');
+
+ // Include the list of proxies
+ if (isset($_SESSION['phpCAS']['proxies'])) {
+ $this->_setProxies($_SESSION['phpCAS']['proxies']);
+ phpCAS::trace(
+ 'proxies = "'
+ .implode('", "', $_SESSION['phpCAS']['proxies']).'"'
+ );
+ }
+
+ $auth = true;
+ } else {
+ phpCAS::trace('no user found');
+ }
+ }
+
+ phpCAS::traceEnd($auth);
+ return $auth;
+ }
+
+ /**
+ * This method is used to redirect the client to the CAS server.
+ * It is used by CAS_Client::forceAuthentication() and
+ * CAS_Client::checkAuthentication().
+ *
+ * @param bool $gateway true to check authentication, false to force it
+ * @param bool $renew true to force the authentication with the CAS server
+ *
+ * @return void
+ */
+ public function redirectToCas($gateway=false,$renew=false)
+ {
+ phpCAS::traceBegin();
+ $cas_url = $this->getServerLoginURL($gateway, $renew);
+ session_write_close();
+ if (php_sapi_name() === 'cli') {
+ @header('Location: '.$cas_url);
+ } else {
+ header('Location: '.$cas_url);
+ }
+ phpCAS::trace("Redirect to : ".$cas_url);
+ $lang = $this->getLangObj();
+ $this->printHTMLHeader($lang->getAuthenticationWanted());
+ printf('<p>'. $lang->getShouldHaveBeenRedirected(). '</p>', $cas_url);
+ $this->printHTMLFooter();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+ }
+
+
+ /**
+ * This method is used to logout from CAS.
+ *
+ * @param array $params an array that contains the optional url and service
+ * parameters that will be passed to the CAS server
+ *
+ * @return void
+ */
+ public function logout($params)
+ {
+ phpCAS::traceBegin();
+ $cas_url = $this->getServerLogoutURL();
+ $paramSeparator = '?';
+ if (isset($params['url'])) {
+ $cas_url = $cas_url . $paramSeparator . "url="
+ . urlencode($params['url']);
+ $paramSeparator = '&';
+ }
+ if (isset($params['service'])) {
+ $cas_url = $cas_url . $paramSeparator . "service="
+ . urlencode($params['service']);
+ }
+ header('Location: '.$cas_url);
+ phpCAS::trace("Prepare redirect to : ".$cas_url);
+
+ phpCAS::trace("Destroying session : ".session_id());
+ session_unset();
+ session_destroy();
+ if (session_status() === PHP_SESSION_NONE) {
+ phpCAS::trace("Session terminated");
+ } else {
+ phpCAS::error("Session was not terminated");
+ phpCAS::trace("Session was not terminated");
+ }
+ $lang = $this->getLangObj();
+ $this->printHTMLHeader($lang->getLogout());
+ printf('<p>'.$lang->getShouldHaveBeenRedirected(). '</p>', $cas_url);
+ $this->printHTMLFooter();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+ }
+
+ /**
+ * Check of the current request is a logout request
+ *
+ * @return bool is logout request.
+ */
+ private function _isLogoutRequest()
+ {
+ return !empty($_POST['logoutRequest']);
+ }
+
+ /**
+ * This method handles logout requests.
+ *
+ * @param bool $check_client true to check the client bofore handling
+ * the request, false not to perform any access control. True by default.
+ * @param array $allowed_clients an array of host names allowed to send
+ * logout requests.
+ *
+ * @return void
+ */
+ public function handleLogoutRequests($check_client=true, $allowed_clients=array())
+ {
+ phpCAS::traceBegin();
+ if (!$this->_isLogoutRequest()) {
+ phpCAS::trace("Not a logout request");
+ phpCAS::traceEnd();
+ return;
+ }
+ if (!$this->getChangeSessionID()
+ && is_null($this->_signoutCallbackFunction)
+ ) {
+ phpCAS::trace(
+ "phpCAS can't handle logout requests if it is not allowed to change session_id."
+ );
+ }
+ phpCAS::trace("Logout requested");
+ $decoded_logout_rq = urldecode($_POST['logoutRequest']);
+ phpCAS::trace("SAML REQUEST: ".$decoded_logout_rq);
+ $allowed = false;
+ if ($check_client) {
+ if ($allowed_clients === array()) {
+ $allowed_clients = array( $this->_getServerHostname() );
+ }
+ $client_ip = $_SERVER['REMOTE_ADDR'];
+ $client = gethostbyaddr($client_ip);
+ phpCAS::trace("Client: ".$client."/".$client_ip);
+ foreach ($allowed_clients as $allowed_client) {
+ if (($client == $allowed_client)
+ || ($client_ip == $allowed_client)
+ ) {
+ phpCAS::trace(
+ "Allowed client '".$allowed_client
+ ."' matches, logout request is allowed"
+ );
+ $allowed = true;
+ break;
+ } else {
+ phpCAS::trace(
+ "Allowed client '".$allowed_client."' does not match"
+ );
+ }
+ }
+ } else {
+ phpCAS::trace("No access control set");
+ $allowed = true;
+ }
+ // If Logout command is permitted proceed with the logout
+ if ($allowed) {
+ phpCAS::trace("Logout command allowed");
+ // Rebroadcast the logout request
+ if ($this->_rebroadcast && !isset($_POST['rebroadcast'])) {
+ $this->_rebroadcast(self::LOGOUT);
+ }
+ // Extract the ticket from the SAML Request
+ preg_match(
+ "|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|",
+ $decoded_logout_rq, $tick, PREG_OFFSET_CAPTURE, 3
+ );
+ $wrappedSamlSessionIndex = preg_replace(
+ '|<samlp:SessionIndex>|', '', $tick[0][0]
+ );
+ $ticket2logout = preg_replace(
+ '|</samlp:SessionIndex>|', '', $wrappedSamlSessionIndex
+ );
+ phpCAS::trace("Ticket to logout: ".$ticket2logout);
+
+ // call the post-authenticate callback if registered.
+ if ($this->_signoutCallbackFunction) {
+ $args = $this->_signoutCallbackArgs;
+ array_unshift($args, $ticket2logout);
+ call_user_func_array($this->_signoutCallbackFunction, $args);
+ }
+
+ // If phpCAS is managing the session_id, destroy session thanks to
+ // session_id.
+ if ($this->getChangeSessionID()) {
+ $session_id = $this->_sessionIdForTicket($ticket2logout);
+ phpCAS::trace("Session id: ".$session_id);
+
+ // destroy a possible application session created before phpcas
+ if (session_id() !== "") {
+ session_unset();
+ session_destroy();
+ }
+ // fix session ID
+ session_id($session_id);
+ $_COOKIE[session_name()]=$session_id;
+ $_GET[session_name()]=$session_id;
+
+ // Overwrite session
+ session_start();
+ session_unset();
+ session_destroy();
+ phpCAS::trace("Session ". $session_id . " destroyed");
+ }
+ } else {
+ phpCAS::error("Unauthorized logout request from client '".$client."'");
+ phpCAS::trace("Unauthorized logout request from client '".$client."'");
+ }
+ flush();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX BASIC CLIENT FEATURES (CAS 1.0) XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ // ########################################################################
+ // ST
+ // ########################################################################
+ /**
+ * @addtogroup internalBasic
+ * @{
+ */
+
+ /**
+ * The Ticket provided in the URL of the request if present
+ * (empty otherwise). Written by CAS_Client::CAS_Client(), read by
+ * CAS_Client::getTicket() and CAS_Client::_hasPGT().
+ *
+ * @hideinitializer
+ */
+ private $_ticket = '';
+
+ /**
+ * This method returns the Service Ticket provided in the URL of the request.
+ *
+ * @return string service ticket.
+ */
+ public function getTicket()
+ {
+ return $this->_ticket;
+ }
+
+ /**
+ * This method stores the Service Ticket.
+ *
+ * @param string $st The Service Ticket.
+ *
+ * @return void
+ */
+ public function setTicket($st)
+ {
+ $this->_ticket = $st;
+ }
+
+ /**
+ * This method tells if a Service Ticket was stored.
+ *
+ * @return bool if a Service Ticket has been stored.
+ */
+ public function hasTicket()
+ {
+ return !empty($this->_ticket);
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // ST VALIDATION
+ // ########################################################################
+ /**
+ * @addtogroup internalBasic
+ * @{
+ */
+
+ /**
+ * @var string the certificate of the CAS server CA.
+ *
+ * @hideinitializer
+ */
+ private $_cas_server_ca_cert = null;
+
+
+ /**
+
+ * validate CN of the CAS server certificate
+
+ *
+
+ * @hideinitializer
+
+ */
+
+ private $_cas_server_cn_validate = true;
+
+ /**
+ * Set to true not to validate the CAS server.
+ *
+ * @hideinitializer
+ */
+ private $_no_cas_server_validation = false;
+
+
+ /**
+ * Set the CA certificate of the CAS server.
+ *
+ * @param string $cert the PEM certificate file name of the CA that emited
+ * the cert of the server
+ * @param bool $validate_cn valiate CN of the CAS server certificate
+ *
+ * @return void
+ */
+ public function setCasServerCACert($cert, $validate_cn)
+ {
+ // Argument validation
+ if (gettype($cert) != 'string') {
+ throw new CAS_TypeMismatchException($cert, '$cert', 'string');
+ }
+ if (gettype($validate_cn) != 'boolean') {
+ throw new CAS_TypeMismatchException($validate_cn, '$validate_cn', 'boolean');
+ }
+ if ( !file_exists($cert) && $this->_requestImplementation !== 'CAS_TestHarness_DummyRequest'){
+ throw new CAS_InvalidArgumentException("Certificate file does not exist " . $this->_requestImplementation);
+ }
+ $this->_cas_server_ca_cert = $cert;
+ $this->_cas_server_cn_validate = $validate_cn;
+ }
+
+ /**
+ * Set no SSL validation for the CAS server.
+ *
+ * @return void
+ */
+ public function setNoCasServerValidation()
+ {
+ $this->_no_cas_server_validation = true;
+ }
+
+ /**
+ * This method is used to validate a CAS 1,0 ticket; halt on failure, and
+ * sets $validate_url, $text_reponse and $tree_response on success.
+ *
+ * @param string &$validate_url reference to the the URL of the request to
+ * the CAS server.
+ * @param string &$text_response reference to the response of the CAS
+ * server, as is (XML text).
+ * @param string &$tree_response reference to the response of the CAS
+ * server, as a DOM XML tree.
+ * @param bool $renew true to force the authentication with the CAS server
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ * @throws CAS_AuthenticationException
+ */
+ public function validateCAS10(&$validate_url,&$text_response,&$tree_response,$renew=false)
+ {
+ phpCAS::traceBegin();
+ // build the URL to validate the ticket
+ $validate_url = $this->getServerServiceValidateURL()
+ .'&ticket='.urlencode($this->getTicket());
+
+ if ( $renew ) {
+ // pass the renew
+ $validate_url .= '&renew=true';
+ }
+
+ // open and read the URL
+ if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
+ phpCAS::trace(
+ 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'
+ );
+ throw new CAS_AuthenticationException(
+ $this, 'CAS 1.0 ticket not validated', $validate_url,
+ true/*$no_response*/
+ );
+ }
+
+ if (preg_match('/^no\n/', $text_response)) {
+ phpCAS::trace('Ticket has not been validated');
+ throw new CAS_AuthenticationException(
+ $this, 'ST not validated', $validate_url, false/*$no_response*/,
+ false/*$bad_response*/, $text_response
+ );
+ } else if (!preg_match('/^yes\n/', $text_response)) {
+ phpCAS::trace('ill-formed response');
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ }
+ // ticket has been validated, extract the user name
+ $arr = preg_split('/\n/', $text_response);
+ $this->_setUser(trim($arr[1]));
+
+ $this->_renameSession($this->getTicket());
+
+ // at this step, ticket has been validated and $this->_user has been set,
+ phpCAS::traceEnd(true);
+ return true;
+ }
+
+ /** @} */
+
+
+ // ########################################################################
+ // SAML VALIDATION
+ // ########################################################################
+ /**
+ * @addtogroup internalSAML
+ * @{
+ */
+
+ /**
+ * This method is used to validate a SAML TICKET; halt on failure, and sets
+ * $validate_url, $text_reponse and $tree_response on success. These
+ * parameters are used later by CAS_Client::_validatePGT() for CAS proxies.
+ *
+ * @param string &$validate_url reference to the the URL of the request to
+ * the CAS server.
+ * @param string &$text_response reference to the response of the CAS
+ * server, as is (XML text).
+ * @param string &$tree_response reference to the response of the CAS
+ * server, as a DOM XML tree.
+ * @param bool $renew true to force the authentication with the CAS server
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ *
+ * @throws CAS_AuthenticationException
+ */
+ public function validateSA(&$validate_url,&$text_response,&$tree_response,$renew=false)
+ {
+ phpCAS::traceBegin();
+ $result = false;
+ // build the URL to validate the ticket
+ $validate_url = $this->getServerSamlValidateURL();
+
+ if ( $renew ) {
+ // pass the renew
+ $validate_url .= '&renew=true';
+ }
+
+ // open and read the URL
+ if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
+ phpCAS::trace(
+ 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'
+ );
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url, true/*$no_response*/
+ );
+ }
+
+ phpCAS::trace('server version: '.$this->getServerVersion());
+
+ // analyze the result depending on the version
+ switch ($this->getServerVersion()) {
+ case SAML_VERSION_1_1:
+ // create new DOMDocument Object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ // read the response of the CAS server into a DOM object
+ if (!($dom->loadXML($text_response))) {
+ phpCAS::trace('dom->loadXML() failed');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ }
+ // read the root node of the XML tree
+ if (!($tree_response = $dom->documentElement)) {
+ phpCAS::trace('documentElement() failed');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ } else if ( $tree_response->localName != 'Envelope' ) {
+ // insure that tag name is 'Envelope'
+ phpCAS::trace(
+ 'bad XML root node (should be `Envelope\' instead of `'
+ .$tree_response->localName.'\''
+ );
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ } else if ($tree_response->getElementsByTagName("NameIdentifier")->length != 0) {
+ // check for the NameIdentifier tag in the SAML response
+ $success_elements = $tree_response->getElementsByTagName("NameIdentifier");
+ phpCAS::trace('NameIdentifier found');
+ $user = trim($success_elements->item(0)->nodeValue);
+ phpCAS::trace('user = `'.$user.'`');
+ $this->_setUser($user);
+ $this->_setSessionAttributes($text_response);
+ $result = true;
+ } else {
+ phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ }
+ }
+ if ($result) {
+ $this->_renameSession($this->getTicket());
+ }
+ // at this step, ST has been validated and $this->_user has been set,
+ phpCAS::traceEnd($result);
+ return $result;
+ }
+
+ /**
+ * This method will parse the DOM and pull out the attributes from the SAML
+ * payload and put them into an array, then put the array into the session.
+ *
+ * @param string $text_response the SAML payload.
+ *
+ * @return bool true when successfull and false if no attributes a found
+ */
+ private function _setSessionAttributes($text_response)
+ {
+ phpCAS::traceBegin();
+
+ $result = false;
+
+ $attr_array = array();
+
+ // create new DOMDocument Object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ if (($dom->loadXML($text_response))) {
+ $xPath = new DOMXPath($dom);
+ $xPath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
+ $xPath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
+ $nodelist = $xPath->query("//saml:Attribute");
+
+ if ($nodelist) {
+ foreach ($nodelist as $node) {
+ $xres = $xPath->query("saml:AttributeValue", $node);
+ $name = $node->getAttribute("AttributeName");
+ $value_array = array();
+ foreach ($xres as $node2) {
+ $value_array[] = $node2->nodeValue;
+ }
+ $attr_array[$name] = $value_array;
+ }
+ // UGent addition...
+ foreach ($attr_array as $attr_key => $attr_value) {
+ if (count($attr_value) > 1) {
+ $this->_attributes[$attr_key] = $attr_value;
+ phpCAS::trace("* " . $attr_key . "=" . print_r($attr_value, true));
+ } else {
+ $this->_attributes[$attr_key] = $attr_value[0];
+ phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]);
+ }
+ }
+ $result = true;
+ } else {
+ phpCAS::trace("SAML Attributes are empty");
+ $result = false;
+ }
+ }
+ phpCAS::traceEnd($result);
+ return $result;
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX PROXY FEATURES (CAS 2.0) XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ // ########################################################################
+ // PROXYING
+ // ########################################################################
+ /**
+ * @addtogroup internalProxy
+ * @{
+ */
+
+ /**
+ * @var bool is the client a proxy
+ * A boolean telling if the client is a CAS proxy or not. Written by
+ * CAS_Client::CAS_Client(), read by CAS_Client::isProxy().
+ */
+ private $_proxy;
+
+ /**
+ * @var CAS_CookieJar Handler for managing service cookies.
+ */
+ private $_serviceCookieJar;
+
+ /**
+ * Tells if a CAS client is a CAS proxy or not
+ *
+ * @return bool true when the CAS client is a CAS proxy, false otherwise
+ */
+ public function isProxy()
+ {
+ return $this->_proxy;
+ }
+
+
+ /** @} */
+ // ########################################################################
+ // PGT
+ // ########################################################################
+ /**
+ * @addtogroup internalProxy
+ * @{
+ */
+
+ /**
+ * the Proxy Grnting Ticket given by the CAS server (empty otherwise).
+ * Written by CAS_Client::_setPGT(), read by CAS_Client::_getPGT() and
+ * CAS_Client::_hasPGT().
+ *
+ * @hideinitializer
+ */
+ private $_pgt = '';
+
+ /**
+ * This method returns the Proxy Granting Ticket given by the CAS server.
+ *
+ * @return string the Proxy Granting Ticket.
+ */
+ private function _getPGT()
+ {
+ return $this->_pgt;
+ }
+
+ /**
+ * This method stores the Proxy Granting Ticket.
+ *
+ * @param string $pgt The Proxy Granting Ticket.
+ *
+ * @return void
+ */
+ private function _setPGT($pgt)
+ {
+ $this->_pgt = $pgt;
+ }
+
+ /**
+ * This method tells if a Proxy Granting Ticket was stored.
+ *
+ * @return bool true if a Proxy Granting Ticket has been stored.
+ */
+ private function _hasPGT()
+ {
+ return !empty($this->_pgt);
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // CALLBACK MODE
+ // ########################################################################
+ /**
+ * @addtogroup internalCallback
+ * @{
+ */
+ /**
+ * each PHP script using phpCAS in proxy mode is its own callback to get the
+ * PGT back from the CAS server. callback_mode is detected by the constructor
+ * thanks to the GET parameters.
+ */
+
+ /**
+ * @var bool a boolean to know if the CAS client is running in callback mode. Written by
+ * CAS_Client::setCallBackMode(), read by CAS_Client::_isCallbackMode().
+ *
+ * @hideinitializer
+ */
+ private $_callback_mode = false;
+
+ /**
+ * This method sets/unsets callback mode.
+ *
+ * @param bool $callback_mode true to set callback mode, false otherwise.
+ *
+ * @return void
+ */
+ private function _setCallbackMode($callback_mode)
+ {
+ $this->_callback_mode = $callback_mode;
+ }
+
+ /**
+ * This method returns true when the CAS client is running in callback mode,
+ * false otherwise.
+ *
+ * @return bool A boolean.
+ */
+ private function _isCallbackMode()
+ {
+ return $this->_callback_mode;
+ }
+
+ /**
+ * the URL that should be used for the PGT callback (in fact the URL of the
+ * current request without any CGI parameter). Written and read by
+ * CAS_Client::_getCallbackURL().
+ *
+ * @hideinitializer
+ */
+ private $_callback_url = '';
+
+ /**
+ * This method returns the URL that should be used for the PGT callback (in
+ * fact the URL of the current request without any CGI parameter, except if
+ * phpCAS::setFixedCallbackURL() was used).
+ *
+ * @return string The callback URL
+ */
+ private function _getCallbackURL()
+ {
+ // the URL is built when needed only
+ if ( empty($this->_callback_url) ) {
+ // remove the ticket if present in the URL
+ $final_uri = 'https://';
+ $final_uri .= $this->_getClientUrl();
+ $request_uri = $_SERVER['REQUEST_URI'];
+ $request_uri = preg_replace('/\?.*$/', '', $request_uri);
+ $final_uri .= $request_uri;
+ $this->_callback_url = $final_uri;
+ }
+ return $this->_callback_url;
+ }
+
+ /**
+ * This method sets the callback url.
+ *
+ * @param string $url url to set callback
+ *
+ * @return string the callback url
+ */
+ public function setCallbackURL($url)
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_callback_url = $url;
+ }
+
+ /**
+ * This method is called by CAS_Client::CAS_Client() when running in callback
+ * mode. It stores the PGT and its PGT Iou, prints its output and halts.
+ *
+ * @return void
+ */
+ private function _callback()
+ {
+ phpCAS::traceBegin();
+ if (preg_match('/^PGTIOU-[\.\-\w]+$/', $_GET['pgtIou'])) {
+ if (preg_match('/^[PT]GT-[\.\-\w]+$/', $_GET['pgtId'])) {
+ $this->printHTMLHeader('phpCAS callback');
+ $pgt_iou = $_GET['pgtIou'];
+ $pgt = $_GET['pgtId'];
+ phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
+ echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
+ $this->_storePGT($pgt, $pgt_iou);
+ $this->printHTMLFooter();
+ phpCAS::traceExit("Successfull Callback");
+ } else {
+ phpCAS::error('PGT format invalid' . $_GET['pgtId']);
+ phpCAS::traceExit('PGT format invalid' . $_GET['pgtId']);
+ }
+ } else {
+ phpCAS::error('PGTiou format invalid' . $_GET['pgtIou']);
+ phpCAS::traceExit('PGTiou format invalid' . $_GET['pgtIou']);
+ }
+
+ // Flush the buffer to prevent from sending anything other then a 200
+ // Success Status back to the CAS Server. The Exception would normally
+ // report as a 500 error.
+ flush();
+ throw new CAS_GracefullTerminationException();
+ }
+
+
+ /** @} */
+
+ // ########################################################################
+ // PGT STORAGE
+ // ########################################################################
+ /**
+ * @addtogroup internalPGTStorage
+ * @{
+ */
+
+ /**
+ * @var CAS_PGTStorage_AbstractStorage
+ * an instance of a class inheriting of PGTStorage, used to deal with PGT
+ * storage. Created by CAS_Client::setPGTStorageFile(), used
+ * by CAS_Client::setPGTStorageFile() and CAS_Client::_initPGTStorage().
+ *
+ * @hideinitializer
+ */
+ private $_pgt_storage = null;
+
+ /**
+ * This method is used to initialize the storage of PGT's.
+ * Halts on error.
+ *
+ * @return void
+ */
+ private function _initPGTStorage()
+ {
+ // if no SetPGTStorageXxx() has been used, default to file
+ if ( !is_object($this->_pgt_storage) ) {
+ $this->setPGTStorageFile();
+ }
+
+ // initializes the storage
+ $this->_pgt_storage->init();
+ }
+
+ /**
+ * This method stores a PGT. Halts on error.
+ *
+ * @param string $pgt the PGT to store
+ * @param string $pgt_iou its corresponding Iou
+ *
+ * @return void
+ */
+ private function _storePGT($pgt,$pgt_iou)
+ {
+ // ensure that storage is initialized
+ $this->_initPGTStorage();
+ // writes the PGT
+ $this->_pgt_storage->write($pgt, $pgt_iou);
+ }
+
+ /**
+ * This method reads a PGT from its Iou and deletes the corresponding
+ * storage entry.
+ *
+ * @param string $pgt_iou the PGT Iou
+ *
+ * @return string mul The PGT corresponding to the Iou, false when not found.
+ */
+ private function _loadPGT($pgt_iou)
+ {
+ // ensure that storage is initialized
+ $this->_initPGTStorage();
+ // read the PGT
+ return $this->_pgt_storage->read($pgt_iou);
+ }
+
+ /**
+ * This method can be used to set a custom PGT storage object.
+ *
+ * @param CAS_PGTStorage_AbstractStorage $storage a PGT storage object that
+ * inherits from the CAS_PGTStorage_AbstractStorage class
+ *
+ * @return void
+ */
+ public function setPGTStorage($storage)
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+
+ // check that the storage has not already been set
+ if ( is_object($this->_pgt_storage) ) {
+ phpCAS::error('PGT storage already defined');
+ }
+
+ // check to make sure a valid storage object was specified
+ if ( !($storage instanceof CAS_PGTStorage_AbstractStorage) )
+ throw new CAS_TypeMismatchException($storage, '$storage', 'CAS_PGTStorage_AbstractStorage object');
+
+ // store the PGTStorage object
+ $this->_pgt_storage = $storage;
+ }
+
+ /**
+ * This method is used to tell phpCAS to store the response of the
+ * CAS server to PGT requests in a database.
+ *
+ * @param string|PDO $dsn_or_pdo a dsn string to use for creating a PDO
+ * object or a PDO object
+ * @param string $username the username to use when connecting to the
+ * database
+ * @param string $password the password to use when connecting to the
+ * database
+ * @param string $table the table to use for storing and retrieving
+ * PGTs
+ * @param string $driver_options any driver options to use when connecting
+ * to the database
+ *
+ * @return void
+ */
+ public function setPGTStorageDb(
+ $dsn_or_pdo, $username='', $password='', $table='', $driver_options=null
+ ) {
+ // Sequence validation
+ $this->ensureIsProxy();
+
+ // Argument validation
+ if (!(is_object($dsn_or_pdo) && $dsn_or_pdo instanceof PDO) && !is_string($dsn_or_pdo))
+ throw new CAS_TypeMismatchException($dsn_or_pdo, '$dsn_or_pdo', 'string or PDO object');
+ if (gettype($username) != 'string')
+ throw new CAS_TypeMismatchException($username, '$username', 'string');
+ if (gettype($password) != 'string')
+ throw new CAS_TypeMismatchException($password, '$password', 'string');
+ if (gettype($table) != 'string')
+ throw new CAS_TypeMismatchException($table, '$password', 'string');
+
+ // create the storage object
+ $this->setPGTStorage(
+ new CAS_PGTStorage_Db(
+ $this, $dsn_or_pdo, $username, $password, $table, $driver_options
+ )
+ );
+ }
+
+ /**
+ * This method is used to tell phpCAS to store the response of the
+ * CAS server to PGT requests onto the filesystem.
+ *
+ * @param string $path the path where the PGT's should be stored
+ *
+ * @return void
+ */
+ public function setPGTStorageFile($path='')
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+
+ // Argument validation
+ if (gettype($path) != 'string')
+ throw new CAS_TypeMismatchException($path, '$path', 'string');
+
+ // create the storage object
+ $this->setPGTStorage(new CAS_PGTStorage_File($this, $path));
+ }
+
+
+ // ########################################################################
+ // PGT VALIDATION
+ // ########################################################################
+ /**
+ * This method is used to validate a PGT; halt on failure.
+ *
+ * @param string &$validate_url the URL of the request to the CAS server.
+ * @param string $text_response the response of the CAS server, as is
+ * (XML text); result of
+ * CAS_Client::validateCAS10() or
+ * CAS_Client::validateCAS20().
+ * @param DOMElement $tree_response the response of the CAS server, as a DOM XML
+ * tree; result of CAS_Client::validateCAS10() or CAS_Client::validateCAS20().
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ *
+ * @throws CAS_AuthenticationException
+ */
+ private function _validatePGT(&$validate_url,$text_response,$tree_response)
+ {
+ phpCAS::traceBegin();
+ if ( $tree_response->getElementsByTagName("proxyGrantingTicket")->length == 0) {
+ phpCAS::trace('<proxyGrantingTicket> not found');
+ // authentication succeded, but no PGT Iou was transmitted
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket validated but no PGT Iou transmitted',
+ $validate_url, false/*$no_response*/, false/*$bad_response*/,
+ $text_response
+ );
+ } else {
+ // PGT Iou transmitted, extract it
+ $pgt_iou = trim(
+ $tree_response->getElementsByTagName("proxyGrantingTicket")->item(0)->nodeValue
+ );
+ if (preg_match('/^PGTIOU-[\.\-\w]+$/', $pgt_iou)) {
+ $pgt = $this->_loadPGT($pgt_iou);
+ if ( $pgt == false ) {
+ phpCAS::trace('could not load PGT');
+ throw new CAS_AuthenticationException(
+ $this,
+ 'PGT Iou was transmitted but PGT could not be retrieved',
+ $validate_url, false/*$no_response*/,
+ false/*$bad_response*/, $text_response
+ );
+ }
+ $this->_setPGT($pgt);
+ } else {
+ phpCAS::trace('PGTiou format error');
+ throw new CAS_AuthenticationException(
+ $this, 'PGT Iou was transmitted but has wrong format',
+ $validate_url, false/*$no_response*/, false/*$bad_response*/,
+ $text_response
+ );
+ }
+ }
+ phpCAS::traceEnd(true);
+ return true;
+ }
+
+ // ########################################################################
+ // PGT VALIDATION
+ // ########################################################################
+
+ /**
+ * This method is used to retrieve PT's from the CAS server thanks to a PGT.
+ *
+ * @param string $target_service the service to ask for with the PT.
+ * @param int &$err_code an error code (PHPCAS_SERVICE_OK on success).
+ * @param string &$err_msg an error message (empty on success).
+ *
+ * @return string|false a Proxy Ticket, or false on error.
+ */
+ public function retrievePT($target_service,&$err_code,&$err_msg)
+ {
+ // Argument validation
+ if (gettype($target_service) != 'string')
+ throw new CAS_TypeMismatchException($target_service, '$target_service', 'string');
+
+ phpCAS::traceBegin();
+
+ // by default, $err_msg is set empty and $pt to true. On error, $pt is
+ // set to false and $err_msg to an error message. At the end, if $pt is false
+ // and $error_msg is still empty, it is set to 'invalid response' (the most
+ // commonly encountered error).
+ $err_msg = '';
+
+ // build the URL to retrieve the PT
+ $cas_url = $this->getServerProxyURL().'?targetService='
+ .urlencode($target_service).'&pgt='.$this->_getPGT();
+
+ // open and read the URL
+ if ( !$this->_readURL($cas_url, $headers, $cas_response, $err_msg) ) {
+ phpCAS::trace(
+ 'could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')'
+ );
+ $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
+ $err_msg = 'could not retrieve PT (no response from the CAS server)';
+ phpCAS::traceEnd(false);
+ return false;
+ }
+
+ $bad_response = false;
+
+ // create new DOMDocument object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ // read the response of the CAS server into a DOM object
+ if ( !($dom->loadXML($cas_response))) {
+ phpCAS::trace('dom->loadXML() failed');
+ // read failed
+ $bad_response = true;
+ }
+
+ if ( !$bad_response ) {
+ // read the root node of the XML tree
+ if ( !($root = $dom->documentElement) ) {
+ phpCAS::trace('documentElement failed');
+ // read failed
+ $bad_response = true;
+ }
+ }
+
+ if ( !$bad_response ) {
+ // insure that tag name is 'serviceResponse'
+ if ( $root->localName != 'serviceResponse' ) {
+ phpCAS::trace('localName failed');
+ // bad root node
+ $bad_response = true;
+ }
+ }
+
+ if ( !$bad_response ) {
+ // look for a proxySuccess tag
+ if ( $root->getElementsByTagName("proxySuccess")->length != 0) {
+ $proxy_success_list = $root->getElementsByTagName("proxySuccess");
+
+ // authentication succeded, look for a proxyTicket tag
+ if ( $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->length != 0) {
+ $err_code = PHPCAS_SERVICE_OK;
+ $err_msg = '';
+ $pt = trim(
+ $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->item(0)->nodeValue
+ );
+ phpCAS::trace('original PT: '.trim($pt));
+ phpCAS::traceEnd($pt);
+ return $pt;
+ } else {
+ phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
+ }
+ } else if ($root->getElementsByTagName("proxyFailure")->length != 0) {
+ // look for a proxyFailure tag
+ $proxy_failure_list = $root->getElementsByTagName("proxyFailure");
+
+ // authentication failed, extract the error
+ $err_code = PHPCAS_SERVICE_PT_FAILURE;
+ $err_msg = 'PT retrieving failed (code=`'
+ .$proxy_failure_list->item(0)->getAttribute('code')
+ .'\', message=`'
+ .trim($proxy_failure_list->item(0)->nodeValue)
+ .'\')';
+ phpCAS::traceEnd(false);
+ return false;
+ } else {
+ phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
+ }
+ }
+
+ // at this step, we are sure that the response of the CAS server was
+ // illformed
+ $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
+ $err_msg = 'Invalid response from the CAS server (response=`'
+ .$cas_response.'\')';
+
+ phpCAS::traceEnd(false);
+ return false;
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // READ CAS SERVER ANSWERS
+ // ########################################################################
+
+ /**
+ * @addtogroup internalMisc
+ * @{
+ */
+
+ /**
+ * This method is used to acces a remote URL.
+ *
+ * @param string $url the URL to access.
+ * @param string &$headers an array containing the HTTP header lines of the
+ * response (an empty array on failure).
+ * @param string &$body the body of the response, as a string (empty on
+ * failure).
+ * @param string &$err_msg an error message, filled on failure.
+ *
+ * @return bool true on success, false otherwise (in this later case, $err_msg
+ * contains an error message).
+ */
+ private function _readURL($url, &$headers, &$body, &$err_msg)
+ {
+ phpCAS::traceBegin();
+ $className = $this->_requestImplementation;
+ $request = new $className();
+
+ if (count($this->_curl_options)) {
+ $request->setCurlOptions($this->_curl_options);
+ }
+
+ $request->setUrl($url);
+
+ if (empty($this->_cas_server_ca_cert) && !$this->_no_cas_server_validation) {
+ phpCAS::error(
+ 'one of the methods phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.'
+ );
+ }
+ if ($this->_cas_server_ca_cert != '') {
+ $request->setSslCaCert(
+ $this->_cas_server_ca_cert, $this->_cas_server_cn_validate
+ );
+ }
+
+ // add extra stuff if SAML
+ if ($this->getServerVersion() == SAML_VERSION_1_1) {
+ $request->addHeader("soapaction: http://www.oasis-open.org/committees/security");
+ $request->addHeader("cache-control: no-cache");
+ $request->addHeader("pragma: no-cache");
+ $request->addHeader("accept: text/xml");
+ $request->addHeader("connection: keep-alive");
+ $request->addHeader("content-type: text/xml");
+ $request->makePost();
+ $request->setPostBody($this->_buildSAMLPayload());
+ }
+
+ if ($request->send()) {
+ $headers = $request->getResponseHeaders();
+ $body = $request->getResponseBody();
+ $err_msg = '';
+ phpCAS::traceEnd(true);
+ return true;
+ } else {
+ $headers = '';
+ $body = '';
+ $err_msg = $request->getErrorMessage();
+ phpCAS::traceEnd(false);
+ return false;
+ }
+ }
+
+ /**
+ * This method is used to build the SAML POST body sent to /samlValidate URL.
+ *
+ * @return string the SOAP-encased SAMLP artifact (the ticket).
+ */
+ private function _buildSAMLPayload()
+ {
+ phpCAS::traceBegin();
+
+ //get the ticket
+ $sa = urlencode($this->getTicket());
+
+ $body = SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST
+ .SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE
+ .SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
+
+ phpCAS::traceEnd($body);
+ return ($body);
+ }
+
+ /** @} **/
+
+ // ########################################################################
+ // ACCESS TO EXTERNAL SERVICES
+ // ########################################################################
+
+ /**
+ * @addtogroup internalProxyServices
+ * @{
+ */
+
+
+ /**
+ * Answer a proxy-authenticated service handler.
+ *
+ * @param string $type The service type. One of:
+ * PHPCAS_PROXIED_SERVICE_HTTP_GET, PHPCAS_PROXIED_SERVICE_HTTP_POST,
+ * PHPCAS_PROXIED_SERVICE_IMAP
+ *
+ * @return CAS_ProxiedService
+ * @throws InvalidArgumentException If the service type is unknown.
+ */
+ public function getProxiedService ($type)
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+ $this->ensureAuthenticationCallSuccessful();
+
+ // Argument validation
+ if (gettype($type) != 'string')
+ throw new CAS_TypeMismatchException($type, '$type', 'string');
+
+ switch ($type) {
+ case PHPCAS_PROXIED_SERVICE_HTTP_GET:
+ case PHPCAS_PROXIED_SERVICE_HTTP_POST:
+ $requestClass = $this->_requestImplementation;
+ $request = new $requestClass();
+ if (count($this->_curl_options)) {
+ $request->setCurlOptions($this->_curl_options);
+ }
+ $proxiedService = new $type($request, $this->_serviceCookieJar);
+ if ($proxiedService instanceof CAS_ProxiedService_Testable) {
+ $proxiedService->setCasClient($this);
+ }
+ return $proxiedService;
+ case PHPCAS_PROXIED_SERVICE_IMAP;
+ $proxiedService = new CAS_ProxiedService_Imap($this->_getUser());
+ if ($proxiedService instanceof CAS_ProxiedService_Testable) {
+ $proxiedService->setCasClient($this);
+ }
+ return $proxiedService;
+ default:
+ throw new CAS_InvalidArgumentException(
+ "Unknown proxied-service type, $type."
+ );
+ }
+ }
+
+ /**
+ * Initialize a proxied-service handler with the proxy-ticket it should use.
+ *
+ * @param CAS_ProxiedService $proxiedService service handler
+ *
+ * @return void
+ *
+ * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
+ * The code of the Exception will be one of:
+ * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_FAILURE
+ * @throws CAS_ProxiedService_Exception If there is a failure getting the
+ * url from the proxied service.
+ */
+ public function initializeProxiedService (CAS_ProxiedService $proxiedService)
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+ $this->ensureAuthenticationCallSuccessful();
+
+ $url = $proxiedService->getServiceUrl();
+ if (!is_string($url)) {
+ throw new CAS_ProxiedService_Exception(
+ "Proxied Service ".get_class($proxiedService)
+ ."->getServiceUrl() should have returned a string, returned a "
+ .gettype($url)." instead."
+ );
+ }
+ $pt = $this->retrievePT($url, $err_code, $err_msg);
+ if (!$pt) {
+ throw new CAS_ProxyTicketException($err_msg, $err_code);
+ }
+ $proxiedService->setProxyTicket($pt);
+ }
+
+ /**
+ * This method is used to access an HTTP[S] service.
+ *
+ * @param string $url the service to access.
+ * @param int &$err_code an error code Possible values are
+ * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
+ * PHPCAS_SERVICE_NOT_AVAILABLE.
+ * @param string &$output the output of the service (also used to give an error
+ * message on failure).
+ *
+ * @return bool true on success, false otherwise (in this later case, $err_code
+ * gives the reason why it failed and $output contains an error message).
+ */
+ public function serviceWeb($url,&$err_code,&$output)
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+ $this->ensureAuthenticationCallSuccessful();
+
+ // Argument validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ try {
+ $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET);
+ $service->setUrl($url);
+ $service->send();
+ $output = $service->getResponseBody();
+ $err_code = PHPCAS_SERVICE_OK;
+ return true;
+ } catch (CAS_ProxyTicketException $e) {
+ $err_code = $e->getCode();
+ $output = $e->getMessage();
+ return false;
+ } catch (CAS_ProxiedService_Exception $e) {
+ $lang = $this->getLangObj();
+ $output = sprintf(
+ $lang->getServiceUnavailable(), $url, $e->getMessage()
+ );
+ $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
+ return false;
+ }
+ }
+
+ /**
+ * This method is used to access an IMAP/POP3/NNTP service.
+ *
+ * @param string $url a string giving the URL of the service, including
+ * the mailing box for IMAP URLs, as accepted by imap_open().
+ * @param string $serviceUrl a string giving for CAS retrieve Proxy ticket
+ * @param string $flags options given to imap_open().
+ * @param int &$err_code an error code Possible values are
+ * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
+ * PHPCAS_SERVICE_NOT_AVAILABLE.
+ * @param string &$err_msg an error message on failure
+ * @param string &$pt the Proxy Ticket (PT) retrieved from the CAS
+ * server to access the URL on success, false on error).
+ *
+ * @return object|false an IMAP stream on success, false otherwise (in this later
+ * case, $err_code gives the reason why it failed and $err_msg contains an
+ * error message).
+ */
+ public function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$pt)
+ {
+ // Sequence validation
+ $this->ensureIsProxy();
+ $this->ensureAuthenticationCallSuccessful();
+
+ // Argument validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+ if (gettype($serviceUrl) != 'string')
+ throw new CAS_TypeMismatchException($serviceUrl, '$serviceUrl', 'string');
+ if (gettype($flags) != 'integer')
+ throw new CAS_TypeMismatchException($flags, '$flags', 'string');
+
+ try {
+ $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_IMAP);
+ $service->setServiceUrl($serviceUrl);
+ $service->setMailbox($url);
+ $service->setOptions($flags);
+
+ $stream = $service->open();
+ $err_code = PHPCAS_SERVICE_OK;
+ $pt = $service->getImapProxyTicket();
+ return $stream;
+ } catch (CAS_ProxyTicketException $e) {
+ $err_msg = $e->getMessage();
+ $err_code = $e->getCode();
+ $pt = false;
+ return false;
+ } catch (CAS_ProxiedService_Exception $e) {
+ $lang = $this->getLangObj();
+ $err_msg = sprintf(
+ $lang->getServiceUnavailable(),
+ $url,
+ $e->getMessage()
+ );
+ $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
+ $pt = false;
+ return false;
+ }
+ }
+
+ /** @} **/
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX PROXIED CLIENT FEATURES (CAS 2.0) XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ // ########################################################################
+ // PT
+ // ########################################################################
+ /**
+ * @addtogroup internalService
+ * @{
+ */
+
+ /**
+ * This array will store a list of proxies in front of this application. This
+ * property will only be populated if this script is being proxied rather than
+ * accessed directly.
+ *
+ * It is set in CAS_Client::validateCAS20() and can be read by
+ * CAS_Client::getProxies()
+ *
+ * @access private
+ */
+ private $_proxies = array();
+
+ /**
+ * Answer an array of proxies that are sitting in front of this application.
+ *
+ * This method will only return a non-empty array if we have received and
+ * validated a Proxy Ticket.
+ *
+ * @return array
+ * @access public
+ */
+ public function getProxies()
+ {
+ return $this->_proxies;
+ }
+
+ /**
+ * Set the Proxy array, probably from persistant storage.
+ *
+ * @param array $proxies An array of proxies
+ *
+ * @return void
+ * @access private
+ */
+ private function _setProxies($proxies)
+ {
+ $this->_proxies = $proxies;
+ if (!empty($proxies)) {
+ // For proxy-authenticated requests people are not viewing the URL
+ // directly since the client is another application making a
+ // web-service call.
+ // Because of this, stripping the ticket from the URL is unnecessary
+ // and causes another web-service request to be performed. Additionally,
+ // if session handling on either the client or the server malfunctions
+ // then the subsequent request will not complete successfully.
+ $this->setNoClearTicketsFromUrl();
+ }
+ }
+
+ /**
+ * A container of patterns to be allowed as proxies in front of the cas client.
+ *
+ * @var CAS_ProxyChain_AllowedList
+ */
+ private $_allowed_proxy_chains;
+
+ /**
+ * Answer the CAS_ProxyChain_AllowedList object for this client.
+ *
+ * @return CAS_ProxyChain_AllowedList
+ */
+ public function getAllowedProxyChains ()
+ {
+ if (empty($this->_allowed_proxy_chains)) {
+ $this->_allowed_proxy_chains = new CAS_ProxyChain_AllowedList();
+ }
+ return $this->_allowed_proxy_chains;
+ }
+
+ /** @} */
+ // ########################################################################
+ // PT VALIDATION
+ // ########################################################################
+ /**
+ * @addtogroup internalProxied
+ * @{
+ */
+
+ /**
+ * This method is used to validate a cas 2.0 ST or PT; halt on failure
+ * Used for all CAS 2.0 validations
+ *
+ * @param string &$validate_url the url of the reponse
+ * @param string &$text_response the text of the repsones
+ * @param DOMElement &$tree_response the domxml tree of the respones
+ * @param bool $renew true to force the authentication with the CAS server
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ *
+ * @throws CAS_AuthenticationException
+ */
+ public function validateCAS20(&$validate_url,&$text_response,&$tree_response, $renew=false)
+ {
+ phpCAS::traceBegin();
+ phpCAS::trace($text_response);
+ // build the URL to validate the ticket
+ if ($this->getAllowedProxyChains()->isProxyingAllowed()) {
+ $validate_url = $this->getServerProxyValidateURL().'&ticket='
+ .urlencode($this->getTicket());
+ } else {
+ $validate_url = $this->getServerServiceValidateURL().'&ticket='
+ .urlencode($this->getTicket());
+ }
+
+ if ( $this->isProxy() ) {
+ // pass the callback url for CAS proxies
+ $validate_url .= '&pgtUrl='.urlencode($this->_getCallbackURL());
+ }
+
+ if ( $renew ) {
+ // pass the renew
+ $validate_url .= '&renew=true';
+ }
+
+ // open and read the URL
+ if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
+ phpCAS::trace(
+ 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')'
+ );
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ true/*$no_response*/
+ );
+ }
+
+ // create new DOMDocument object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ // CAS servers should only return data in utf-8
+ $dom->encoding = "utf-8";
+ // read the response of the CAS server into a DOMDocument object
+ if ( !($dom->loadXML($text_response))) {
+ // read failed
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ } else if ( !($tree_response = $dom->documentElement) ) {
+ // read the root node of the XML tree
+ // read failed
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ } else if ($tree_response->localName != 'serviceResponse') {
+ // insure that tag name is 'serviceResponse'
+ // bad root node
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ } else if ( $tree_response->getElementsByTagName("authenticationFailure")->length != 0) {
+ // authentication failed, extract the error code and message and throw exception
+ $auth_fail_list = $tree_response
+ ->getElementsByTagName("authenticationFailure");
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, false/*$bad_response*/,
+ $text_response,
+ $auth_fail_list->item(0)->getAttribute('code')/*$err_code*/,
+ trim($auth_fail_list->item(0)->nodeValue)/*$err_msg*/
+ );
+ } else if ($tree_response->getElementsByTagName("authenticationSuccess")->length != 0) {
+ // authentication succeded, extract the user name
+ $success_elements = $tree_response
+ ->getElementsByTagName("authenticationSuccess");
+ if ( $success_elements->item(0)->getElementsByTagName("user")->length == 0) {
+ // no user specified => error
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ } else {
+ $this->_setUser(
+ trim(
+ $success_elements->item(0)->getElementsByTagName("user")->item(0)->nodeValue
+ )
+ );
+ $this->_readExtraAttributesCas20($success_elements);
+ // Store the proxies we are sitting behind for authorization checking
+ $proxyList = array();
+ if ( sizeof($arr = $success_elements->item(0)->getElementsByTagName("proxy")) > 0) {
+ foreach ($arr as $proxyElem) {
+ phpCAS::trace("Found Proxy: ".$proxyElem->nodeValue);
+ $proxyList[] = trim($proxyElem->nodeValue);
+ }
+ $this->_setProxies($proxyList);
+ phpCAS::trace("Storing Proxy List");
+ }
+ // Check if the proxies in front of us are allowed
+ if (!$this->getAllowedProxyChains()->isProxyListAllowed($proxyList)) {
+ throw new CAS_AuthenticationException(
+ $this, 'Proxy not allowed', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ } else {
+ $result = true;
+ }
+ }
+ } else {
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ }
+
+ $this->_renameSession($this->getTicket());
+
+ // at this step, Ticket has been validated and $this->_user has been set,
+
+ phpCAS::traceEnd($result);
+ return $result;
+ }
+
+
+ /**
+ * This method will parse the DOM and pull out the attributes from the XML
+ * payload and put them into an array, then put the array into the session.
+ *
+ * @param DOMNodeList $success_elements payload of the response
+ *
+ * @return bool true when successfull, halt otherwise by calling
+ * CAS_Client::_authError().
+ */
+ private function _readExtraAttributesCas20($success_elements)
+ {
+ phpCAS::traceBegin();
+
+ $extra_attributes = array();
+
+ // "Jasig Style" Attributes:
+ //
+ // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ // <cas:authenticationSuccess>
+ // <cas:user>jsmith</cas:user>
+ // <cas:attributes>
+ // <cas:attraStyle>RubyCAS</cas:attraStyle>
+ // <cas:surname>Smith</cas:surname>
+ // <cas:givenName>John</cas:givenName>
+ // <cas:memberOf>CN=Staff,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ // <cas:memberOf>CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ // </cas:attributes>
+ // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
+ // </cas:authenticationSuccess>
+ // </cas:serviceResponse>
+ //
+ if ($this->_casAttributeParserCallbackFunction !== null
+ && is_callable($this->_casAttributeParserCallbackFunction)
+ ) {
+ array_unshift($this->_casAttributeParserCallbackArgs, $success_elements->item(0));
+ phpCAS :: trace("Calling attritubeParser callback");
+ $extra_attributes = call_user_func_array(
+ $this->_casAttributeParserCallbackFunction,
+ $this->_casAttributeParserCallbackArgs
+ );
+ } elseif ( $success_elements->item(0)->getElementsByTagName("attributes")->length != 0) {
+ $attr_nodes = $success_elements->item(0)
+ ->getElementsByTagName("attributes");
+ phpCAS :: trace("Found nested jasig style attributes");
+ if ($attr_nodes->item(0)->hasChildNodes()) {
+ // Nested Attributes
+ foreach ($attr_nodes->item(0)->childNodes as $attr_child) {
+ phpCAS :: trace(
+ "Attribute [".$attr_child->localName."] = "
+ .$attr_child->nodeValue
+ );
+ $this->_addAttributeToArray(
+ $extra_attributes, $attr_child->localName,
+ $attr_child->nodeValue
+ );
+ }
+ }
+ } else {
+ // "RubyCAS Style" attributes
+ //
+ // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ // <cas:authenticationSuccess>
+ // <cas:user>jsmith</cas:user>
+ //
+ // <cas:attraStyle>RubyCAS</cas:attraStyle>
+ // <cas:surname>Smith</cas:surname>
+ // <cas:givenName>John</cas:givenName>
+ // <cas:memberOf>CN=Staff,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ // <cas:memberOf>CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ //
+ // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
+ // </cas:authenticationSuccess>
+ // </cas:serviceResponse>
+ //
+ phpCAS :: trace("Testing for rubycas style attributes");
+ $childnodes = $success_elements->item(0)->childNodes;
+ foreach ($childnodes as $attr_node) {
+ switch ($attr_node->localName) {
+ case 'user':
+ case 'proxies':
+ case 'proxyGrantingTicket':
+ break;
+ default:
+ if (strlen(trim($attr_node->nodeValue))) {
+ phpCAS :: trace(
+ "Attribute [".$attr_node->localName."] = ".$attr_node->nodeValue
+ );
+ $this->_addAttributeToArray(
+ $extra_attributes, $attr_node->localName,
+ $attr_node->nodeValue
+ );
+ }
+ }
+ }
+ }
+
+ // "Name-Value" attributes.
+ //
+ // Attribute format from these mailing list thread:
+ // http://jasig.275507.n4.nabble.com/CAS-attributes-and-how-they-appear-in-the-CAS-response-td264272.html
+ // Note: This is a less widely used format, but in use by at least two institutions.
+ //
+ // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ // <cas:authenticationSuccess>
+ // <cas:user>jsmith</cas:user>
+ //
+ // <cas:attribute name='attraStyle' value='Name-Value' />
+ // <cas:attribute name='surname' value='Smith' />
+ // <cas:attribute name='givenName' value='John' />
+ // <cas:attribute name='memberOf' value='CN=Staff,OU=Groups,DC=example,DC=edu' />
+ // <cas:attribute name='memberOf' value='CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu' />
+ //
+ // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
+ // </cas:authenticationSuccess>
+ // </cas:serviceResponse>
+ //
+ if (!count($extra_attributes)
+ && $success_elements->item(0)->getElementsByTagName("attribute")->length != 0
+ ) {
+ $attr_nodes = $success_elements->item(0)
+ ->getElementsByTagName("attribute");
+ $firstAttr = $attr_nodes->item(0);
+ if (!$firstAttr->hasChildNodes()
+ && $firstAttr->hasAttribute('name')
+ && $firstAttr->hasAttribute('value')
+ ) {
+ phpCAS :: trace("Found Name-Value style attributes");
+ // Nested Attributes
+ foreach ($attr_nodes as $attr_node) {
+ if ($attr_node->hasAttribute('name')
+ && $attr_node->hasAttribute('value')
+ ) {
+ phpCAS :: trace(
+ "Attribute [".$attr_node->getAttribute('name')
+ ."] = ".$attr_node->getAttribute('value')
+ );
+ $this->_addAttributeToArray(
+ $extra_attributes, $attr_node->getAttribute('name'),
+ $attr_node->getAttribute('value')
+ );
+ }
+ }
+ }
+ }
+
+ $this->setAttributes($extra_attributes);
+ phpCAS::traceEnd();
+ return true;
+ }
+
+ /**
+ * Add an attribute value to an array of attributes.
+ *
+ * @param array &$attributeArray reference to array
+ * @param string $name name of attribute
+ * @param string $value value of attribute
+ *
+ * @return void
+ */
+ private function _addAttributeToArray(array &$attributeArray, $name, $value)
+ {
+ // If multiple attributes exist, add as an array value
+ if (isset($attributeArray[$name])) {
+ // Initialize the array with the existing value
+ if (!is_array($attributeArray[$name])) {
+ $existingValue = $attributeArray[$name];
+ $attributeArray[$name] = array($existingValue);
+ }
+
+ $attributeArray[$name][] = trim($value);
+ } else {
+ $attributeArray[$name] = trim($value);
+ }
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX MISC XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ /**
+ * @addtogroup internalMisc
+ * @{
+ */
+
+ // ########################################################################
+ // URL
+ // ########################################################################
+ /**
+ * the URL of the current request (without any ticket CGI parameter). Written
+ * and read by CAS_Client::getURL().
+ *
+ * @hideinitializer
+ */
+ private $_url = '';
+
+
+ /**
+ * This method sets the URL of the current request
+ *
+ * @param string $url url to set for service
+ *
+ * @return void
+ */
+ public function setURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ $this->_url = $url;
+ }
+
+ /**
+ * This method returns the URL of the current request (without any ticket
+ * CGI parameter).
+ *
+ * @return string The URL
+ */
+ public function getURL()
+ {
+ phpCAS::traceBegin();
+ // the URL is built when needed only
+ if ( empty($this->_url) ) {
+ // remove the ticket if present in the URL
+ $final_uri = ($this->_isHttps()) ? 'https' : 'http';
+ $final_uri .= '://';
+
+ $final_uri .= $this->_getClientUrl();
+ $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2);
+ $final_uri .= $request_uri[0];
+
+ if (isset($request_uri[1]) && $request_uri[1]) {
+ $query_string= $this->_removeParameterFromQueryString('ticket', $request_uri[1]);
+
+ // If the query string still has anything left,
+ // append it to the final URI
+ if ($query_string !== '') {
+ $final_uri .= "?$query_string";
+ }
+ }
+
+ phpCAS::trace("Final URI: $final_uri");
+ $this->setURL($final_uri);
+ }
+ phpCAS::traceEnd($this->_url);
+ return $this->_url;
+ }
+
+ /**
+ * This method sets the base URL of the CAS server.
+ *
+ * @param string $url the base URL
+ *
+ * @return string base url
+ */
+ public function setBaseURL($url)
+ {
+ // Argument Validation
+ if (gettype($url) != 'string')
+ throw new CAS_TypeMismatchException($url, '$url', 'string');
+
+ return $this->_server['base_url'] = $url;
+ }
+
+
+ /**
+ * Try to figure out the phpCAS client URL with possible Proxys / Ports etc.
+ *
+ * @return string Server URL with domain:port
+ */
+ private function _getClientUrl()
+ {
+ if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
+ // explode the host list separated by comma and use the first host
+ $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
+ // see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default
+ return $hosts[0];
+ } else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
+ $server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
+ } else {
+ if (empty($_SERVER['SERVER_NAME'])) {
+ $server_url = $_SERVER['HTTP_HOST'];
+ } else {
+ $server_url = $_SERVER['SERVER_NAME'];
+ }
+ }
+ if (!strpos($server_url, ':')) {
+ if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
+ $server_port = $_SERVER['SERVER_PORT'];
+ } else {
+ $ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
+ $server_port = $ports[0];
+ }
+
+ if ( ($this->_isHttps() && $server_port!=443)
+ || (!$this->_isHttps() && $server_port!=80)
+ ) {
+ $server_url .= ':';
+ $server_url .= $server_port;
+ }
+ }
+ return $server_url;
+ }
+
+ /**
+ * This method checks to see if the request is secured via HTTPS
+ *
+ * @return bool true if https, false otherwise
+ */
+ private function _isHttps()
+ {
+ if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
+ return ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
+ } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) {
+ return ($_SERVER['HTTP_X_FORWARDED_PROTOCOL'] === 'https');
+ } elseif ( isset($_SERVER['HTTPS'])
+ && !empty($_SERVER['HTTPS'])
+ && strcasecmp($_SERVER['HTTPS'], 'off') !== 0
+ ) {
+ return true;
+ }
+ return false;
+
+ }
+
+ /**
+ * Removes a parameter from a query string
+ *
+ * @param string $parameterName name of parameter
+ * @param string $queryString query string
+ *
+ * @return string new query string
+ *
+ * @link http://stackoverflow.com/questions/1842681/regular-expression-to-remove-one-parameter-from-query-string
+ */
+ private function _removeParameterFromQueryString($parameterName, $queryString)
+ {
+ $parameterName = preg_quote($parameterName);
+ return preg_replace(
+ "/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/",
+ '', $queryString
+ );
+ }
+
+ /**
+ * This method is used to append query parameters to an url. Since the url
+ * might already contain parameter it has to be detected and to build a proper
+ * URL
+ *
+ * @param string $url base url to add the query params to
+ * @param string $query params in query form with & separated
+ *
+ * @return string url with query params
+ */
+ private function _buildQueryUrl($url, $query)
+ {
+ $url .= (strstr($url, '?') === false) ? '?' : '&';
+ $url .= $query;
+ return $url;
+ }
+
+ /**
+ * Renaming the session
+ *
+ * @param string $ticket name of the ticket
+ *
+ * @return void
+ */
+ private function _renameSession($ticket)
+ {
+ phpCAS::traceBegin();
+ if ($this->getChangeSessionID()) {
+ if (!empty($this->_user)) {
+ $old_session = $_SESSION;
+ phpCAS :: trace("Killing session: ". session_id());
+ session_destroy();
+ // set up a new session, of name based on the ticket
+ $session_id = $this->_sessionIdForTicket($ticket);
+ phpCAS :: trace("Starting session: ". $session_id);
+ session_id($session_id);
+ session_start();
+ phpCAS :: trace("Restoring old session vars");
+ $_SESSION = $old_session;
+ } else {
+ phpCAS :: trace (
+ 'Session should only be renamed after successfull authentication'
+ );
+ }
+ } else {
+ phpCAS :: trace(
+ "Skipping session rename since phpCAS is not handling the session."
+ );
+ }
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * Answer a valid session-id given a CAS ticket.
+ *
+ * The output must be deterministic to allow single-log-out when presented with
+ * the ticket to log-out.
+ *
+ *
+ * @param string $ticket name of the ticket
+ *
+ * @return string
+ */
+ private function _sessionIdForTicket($ticket)
+ {
+ // Hash the ticket to ensure that the value meets the PHP 7.1 requirement
+ // that session-ids have a length between 22 and 256 characters.
+ return hash('sha256', $this->_sessionIdSalt . $ticket);
+ }
+
+ /**
+ * Set a salt/seed for the session-id hash to make it harder to guess.
+ *
+ * @var string $_sessionIdSalt
+ */
+ private $_sessionIdSalt = '';
+
+ /**
+ * Set a salt/seed for the session-id hash to make it harder to guess.
+ *
+ * @param string $salt
+ *
+ * @return void
+ */
+ public function setSessionIdSalt($salt) {
+ $this->_sessionIdSalt = (string)$salt;
+ }
+
+ // ########################################################################
+ // AUTHENTICATION ERROR HANDLING
+ // ########################################################################
+ /**
+ * This method is used to print the HTML output when the user was not
+ * authenticated.
+ *
+ * @param string $failure the failure that occured
+ * @param string $cas_url the URL the CAS server was asked for
+ * @param bool $no_response the response from the CAS server (other
+ * parameters are ignored if true)
+ * @param bool $bad_response bad response from the CAS server ($err_code
+ * and $err_msg ignored if true)
+ * @param string $cas_response the response of the CAS server
+ * @param int $err_code the error code given by the CAS server
+ * @param string $err_msg the error message given by the CAS server
+ *
+ * @return void
+ */
+ private function _authError(
+ $failure,
+ $cas_url,
+ $no_response=false,
+ $bad_response=false,
+ $cas_response='',
+ $err_code=-1,
+ $err_msg=''
+ ) {
+ phpCAS::traceBegin();
+ $lang = $this->getLangObj();
+ $this->printHTMLHeader($lang->getAuthenticationFailed());
+ printf(
+ $lang->getYouWereNotAuthenticated(), htmlentities($this->getURL()),
+ isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN']:''
+ );
+ phpCAS::trace('CAS URL: '.$cas_url);
+ phpCAS::trace('Authentication failure: '.$failure);
+ if ( $no_response ) {
+ phpCAS::trace('Reason: no response from the CAS server');
+ } else {
+ if ( $bad_response ) {
+ phpCAS::trace('Reason: bad response from the CAS server');
+ } else {
+ switch ($this->getServerVersion()) {
+ case CAS_VERSION_1_0:
+ phpCAS::trace('Reason: CAS error');
+ break;
+ case CAS_VERSION_2_0:
+ case CAS_VERSION_3_0:
+ if ( $err_code === -1 ) {
+ phpCAS::trace('Reason: no CAS error');
+ } else {
+ phpCAS::trace(
+ 'Reason: ['.$err_code.'] CAS error: '.$err_msg
+ );
+ }
+ break;
+ }
+ }
+ phpCAS::trace('CAS response: '.$cas_response);
+ }
+ $this->printHTMLFooter();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+ }
+
+ // ########################################################################
+ // PGTIOU/PGTID and logoutRequest rebroadcasting
+ // ########################################################################
+
+ /**
+ * Boolean of whether to rebroadcast pgtIou/pgtId and logoutRequest, and
+ * array of the nodes.
+ */
+ private $_rebroadcast = false;
+ private $_rebroadcast_nodes = array();
+
+ /**
+ * Constants used for determining rebroadcast node type.
+ */
+ const HOSTNAME = 0;
+ const IP = 1;
+
+ /**
+ * Determine the node type from the URL.
+ *
+ * @param String $nodeURL The node URL.
+ *
+ * @return int hostname
+ *
+ */
+ private function _getNodeType($nodeURL)
+ {
+ phpCAS::traceBegin();
+ if (preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $nodeURL)) {
+ phpCAS::traceEnd(self::IP);
+ return self::IP;
+ } else {
+ phpCAS::traceEnd(self::HOSTNAME);
+ return self::HOSTNAME;
+ }
+ }
+
+ /**
+ * Store the rebroadcast node for pgtIou/pgtId and logout requests.
+ *
+ * @param string $rebroadcastNodeUrl The rebroadcast node URL.
+ *
+ * @return void
+ */
+ public function addRebroadcastNode($rebroadcastNodeUrl)
+ {
+ // Argument validation
+ if ( !(bool)preg_match("/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $rebroadcastNodeUrl))
+ throw new CAS_TypeMismatchException($rebroadcastNodeUrl, '$rebroadcastNodeUrl', 'url');
+
+ // Store the rebroadcast node and set flag
+ $this->_rebroadcast = true;
+ $this->_rebroadcast_nodes[] = $rebroadcastNodeUrl;
+ }
+
+ /**
+ * An array to store extra rebroadcast curl options.
+ */
+ private $_rebroadcast_headers = array();
+
+ /**
+ * This method is used to add header parameters when rebroadcasting
+ * pgtIou/pgtId or logoutRequest.
+ *
+ * @param string $header Header to send when rebroadcasting.
+ *
+ * @return void
+ */
+ public function addRebroadcastHeader($header)
+ {
+ if (gettype($header) != 'string')
+ throw new CAS_TypeMismatchException($header, '$header', 'string');
+
+ $this->_rebroadcast_headers[] = $header;
+ }
+
+ /**
+ * Constants used for determining rebroadcast type (logout or pgtIou/pgtId).
+ */
+ const LOGOUT = 0;
+ const PGTIOU = 1;
+
+ /**
+ * This method rebroadcasts logout/pgtIou requests. Can be LOGOUT,PGTIOU
+ *
+ * @param int $type type of rebroadcasting.
+ *
+ * @return void
+ */
+ private function _rebroadcast($type)
+ {
+ phpCAS::traceBegin();
+
+ $rebroadcast_curl_options = array(
+ CURLOPT_FAILONERROR => 1,
+ CURLOPT_FOLLOWLOCATION => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_CONNECTTIMEOUT => 1,
+ CURLOPT_TIMEOUT => 4);
+
+ // Try to determine the IP address of the server
+ if (!empty($_SERVER['SERVER_ADDR'])) {
+ $ip = $_SERVER['SERVER_ADDR'];
+ } else if (!empty($_SERVER['LOCAL_ADDR'])) {
+ // IIS 7
+ $ip = $_SERVER['LOCAL_ADDR'];
+ }
+ // Try to determine the DNS name of the server
+ if (!empty($ip)) {
+ $dns = gethostbyaddr($ip);
+ }
+ $multiClassName = 'CAS_Request_CurlMultiRequest';
+ $multiRequest = new $multiClassName();
+
+ for ($i = 0; $i < sizeof($this->_rebroadcast_nodes); $i++) {
+ if ((($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::HOSTNAME) && !empty($dns) && (stripos($this->_rebroadcast_nodes[$i], $dns) === false))
+ || (($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::IP) && !empty($ip) && (stripos($this->_rebroadcast_nodes[$i], $ip) === false))
+ ) {
+ phpCAS::trace(
+ 'Rebroadcast target URL: '.$this->_rebroadcast_nodes[$i]
+ .$_SERVER['REQUEST_URI']
+ );
+ $className = $this->_requestImplementation;
+ $request = new $className();
+
+ $url = $this->_rebroadcast_nodes[$i].$_SERVER['REQUEST_URI'];
+ $request->setUrl($url);
+
+ if (count($this->_rebroadcast_headers)) {
+ $request->addHeaders($this->_rebroadcast_headers);
+ }
+
+ $request->makePost();
+ if ($type == self::LOGOUT) {
+ // Logout request
+ $request->setPostBody(
+ 'rebroadcast=false&logoutRequest='.$_POST['logoutRequest']
+ );
+ } else if ($type == self::PGTIOU) {
+ // pgtIou/pgtId rebroadcast
+ $request->setPostBody('rebroadcast=false');
+ }
+
+ $request->setCurlOptions($rebroadcast_curl_options);
+
+ $multiRequest->addRequest($request);
+ } else {
+ phpCAS::trace(
+ 'Rebroadcast not sent to self: '
+ .$this->_rebroadcast_nodes[$i].' == '.(!empty($ip)?$ip:'')
+ .'/'.(!empty($dns)?$dns:'')
+ );
+ }
+ }
+ // We need at least 1 request
+ if ($multiRequest->getNumRequests() > 0) {
+ $multiRequest->send();
+ }
+ phpCAS::traceEnd();
+ }
+
+ /** @} */
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/CookieJar.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class provides access to service cookies and handles parsing of response
+ * headers to pull out cookie values.
+ *
+ * @class CAS_CookieJar
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_CookieJar
+{
+
+ private $_cookies;
+
+ /**
+ * Create a new cookie jar by passing it a reference to an array in which it
+ * should store cookies.
+ *
+ * @param array &$storageArray Array to store cookies
+ *
+ * @return void
+ */
+ public function __construct (array &$storageArray)
+ {
+ $this->_cookies =& $storageArray;
+ }
+
+ /**
+ * Store cookies for a web service request.
+ * Cookie storage is based on RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
+ *
+ * @param string $request_url The URL that generated the response headers.
+ * @param array $response_headers An array of the HTTP response header strings.
+ *
+ * @return void
+ *
+ * @access private
+ */
+ public function storeCookies ($request_url, $response_headers)
+ {
+ $urlParts = parse_url($request_url);
+ $defaultDomain = $urlParts['host'];
+
+ $cookies = $this->parseCookieHeaders($response_headers, $defaultDomain);
+
+ foreach ($cookies as $cookie) {
+ // Enforce the same-origin policy by verifying that the cookie
+ // would match the url that is setting it
+ if (!$this->cookieMatchesTarget($cookie, $urlParts)) {
+ continue;
+ }
+
+ // store the cookie
+ $this->storeCookie($cookie);
+
+ phpCAS::trace($cookie['name'].' -> '.$cookie['value']);
+ }
+ }
+
+ /**
+ * Retrieve cookies applicable for a web service request.
+ * Cookie applicability is based on RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
+ *
+ * @param string $request_url The url that the cookies will be for.
+ *
+ * @return array An array containing cookies. E.g. array('name' => 'val');
+ *
+ * @access private
+ */
+ public function getCookies ($request_url)
+ {
+ if (!count($this->_cookies)) {
+ return array();
+ }
+
+ // If our request URL can't be parsed, no cookies apply.
+ $target = parse_url($request_url);
+ if ($target === false) {
+ return array();
+ }
+
+ $this->expireCookies();
+
+ $matching_cookies = array();
+ foreach ($this->_cookies as $key => $cookie) {
+ if ($this->cookieMatchesTarget($cookie, $target)) {
+ $matching_cookies[$cookie['name']] = $cookie['value'];
+ }
+ }
+ return $matching_cookies;
+ }
+
+
+ /**
+ * Parse Cookies without PECL
+ * From the comments in http://php.net/manual/en/function.http-parse-cookie.php
+ *
+ * @param array $header array of header lines.
+ * @param string $defaultDomain The domain to use if none is specified in
+ * the cookie.
+ *
+ * @return array of cookies
+ */
+ protected function parseCookieHeaders( $header, $defaultDomain )
+ {
+ phpCAS::traceBegin();
+ $cookies = array();
+ foreach ( $header as $line ) {
+ if ( preg_match('/^Set-Cookie2?: /i', $line)) {
+ $cookies[] = $this->parseCookieHeader($line, $defaultDomain);
+ }
+ }
+
+ phpCAS::traceEnd($cookies);
+ return $cookies;
+ }
+
+ /**
+ * Parse a single cookie header line.
+ *
+ * Based on RFC2965 http://www.ietf.org/rfc/rfc2965.txt
+ *
+ * @param string $line The header line.
+ * @param string $defaultDomain The domain to use if none is specified in
+ * the cookie.
+ *
+ * @return array
+ */
+ protected function parseCookieHeader ($line, $defaultDomain)
+ {
+ if (!$defaultDomain) {
+ throw new CAS_InvalidArgumentException(
+ '$defaultDomain was not provided.'
+ );
+ }
+
+ // Set our default values
+ $cookie = array(
+ 'domain' => $defaultDomain,
+ 'path' => '/',
+ 'secure' => false,
+ );
+
+ $line = preg_replace('/^Set-Cookie2?: /i', '', trim($line));
+
+ // trim any trailing semicolons.
+ $line = trim($line, ';');
+
+ phpCAS::trace("Cookie Line: $line");
+
+ // This implementation makes the assumption that semicolons will not
+ // be present in quoted attribute values. While attribute values that
+ // contain semicolons are allowed by RFC2965, they are hopefully rare
+ // enough to ignore for our purposes. Most browsers make the same
+ // assumption.
+ $attributeStrings = explode(';', $line);
+
+ foreach ( $attributeStrings as $attributeString ) {
+ // split on the first equals sign and use the rest as value
+ $attributeParts = explode('=', $attributeString, 2);
+
+ $attributeName = trim($attributeParts[0]);
+ $attributeNameLC = strtolower($attributeName);
+
+ if (isset($attributeParts[1])) {
+ $attributeValue = trim($attributeParts[1]);
+ // Values may be quoted strings.
+ if (strpos($attributeValue, '"') === 0) {
+ $attributeValue = trim($attributeValue, '"');
+ // unescape any escaped quotes:
+ $attributeValue = str_replace('\"', '"', $attributeValue);
+ }
+ } else {
+ $attributeValue = null;
+ }
+
+ switch ($attributeNameLC) {
+ case 'expires':
+ $cookie['expires'] = strtotime($attributeValue);
+ break;
+ case 'max-age':
+ $cookie['max-age'] = (int)$attributeValue;
+ // Set an expiry time based on the max-age
+ if ($cookie['max-age']) {
+ $cookie['expires'] = time() + $cookie['max-age'];
+ } else {
+ // If max-age is zero, then the cookie should be removed
+ // imediately so set an expiry before now.
+ $cookie['expires'] = time() - 1;
+ }
+ break;
+ case 'secure':
+ $cookie['secure'] = true;
+ break;
+ case 'domain':
+ case 'path':
+ case 'port':
+ case 'version':
+ case 'comment':
+ case 'commenturl':
+ case 'discard':
+ case 'httponly':
+ $cookie[$attributeNameLC] = $attributeValue;
+ break;
+ default:
+ $cookie['name'] = $attributeName;
+ $cookie['value'] = $attributeValue;
+ }
+ }
+
+ return $cookie;
+ }
+
+ /**
+ * Add, update, or remove a cookie.
+ *
+ * @param array $cookie A cookie array as created by parseCookieHeaders()
+ *
+ * @return void
+ *
+ * @access protected
+ */
+ protected function storeCookie ($cookie)
+ {
+ // Discard any old versions of this cookie.
+ $this->discardCookie($cookie);
+ $this->_cookies[] = $cookie;
+
+ }
+
+ /**
+ * Discard an existing cookie
+ *
+ * @param array $cookie An cookie
+ *
+ * @return void
+ *
+ * @access protected
+ */
+ protected function discardCookie ($cookie)
+ {
+ if (!isset($cookie['domain'])
+ || !isset($cookie['path'])
+ || !isset($cookie['path'])
+ ) {
+ throw new CAS_InvalidArgumentException('Invalid Cookie array passed.');
+ }
+
+ foreach ($this->_cookies as $key => $old_cookie) {
+ if ( $cookie['domain'] == $old_cookie['domain']
+ && $cookie['path'] == $old_cookie['path']
+ && $cookie['name'] == $old_cookie['name']
+ ) {
+ unset($this->_cookies[$key]);
+ }
+ }
+ }
+
+ /**
+ * Go through our stored cookies and remove any that are expired.
+ *
+ * @return void
+ *
+ * @access protected
+ */
+ protected function expireCookies ()
+ {
+ foreach ($this->_cookies as $key => $cookie) {
+ if (isset($cookie['expires']) && $cookie['expires'] < time()) {
+ unset($this->_cookies[$key]);
+ }
+ }
+ }
+
+ /**
+ * Answer true if cookie is applicable to a target.
+ *
+ * @param array $cookie An array of cookie attributes.
+ * @param array|false $target An array of URL attributes as generated by parse_url().
+ *
+ * @return bool
+ *
+ * @access private
+ */
+ protected function cookieMatchesTarget ($cookie, $target)
+ {
+ if (!is_array($target)) {
+ throw new CAS_InvalidArgumentException(
+ '$target must be an array of URL attributes as generated by parse_url().'
+ );
+ }
+ if (!isset($target['host'])) {
+ throw new CAS_InvalidArgumentException(
+ '$target must be an array of URL attributes as generated by parse_url().'
+ );
+ }
+
+ // Verify that the scheme matches
+ if ($cookie['secure'] && $target['scheme'] != 'https') {
+ return false;
+ }
+
+ // Verify that the host matches
+ // Match domain and mulit-host cookies
+ if (strpos($cookie['domain'], '.') === 0) {
+ // .host.domain.edu cookies are valid for host.domain.edu
+ if (substr($cookie['domain'], 1) == $target['host']) {
+ // continue with other checks
+ } else {
+ // non-exact host-name matches.
+ // check that the target host a.b.c.edu is within .b.c.edu
+ $pos = strripos($target['host'], $cookie['domain']);
+ if (!$pos) {
+ return false;
+ }
+ // verify that the cookie domain is the last part of the host.
+ if ($pos + strlen($cookie['domain']) != strlen($target['host'])) {
+ return false;
+ }
+ // verify that the host name does not contain interior dots as per
+ // RFC 2965 section 3.3.2 Rejecting Cookies
+ // http://www.ietf.org/rfc/rfc2965.txt
+ $hostname = substr($target['host'], 0, $pos);
+ if (strpos($hostname, '.') !== false) {
+ return false;
+ }
+ }
+ } else {
+ // If the cookie host doesn't begin with '.',
+ // the host must case-insensitive match exactly
+ if (strcasecmp($target['host'], $cookie['domain']) !== 0) {
+ return false;
+ }
+ }
+
+ // Verify that the port matches
+ if (isset($cookie['ports'])
+ && !in_array($target['port'], $cookie['ports'])
+ ) {
+ return false;
+ }
+
+ // Verify that the path matches
+ if (strpos($target['path'], $cookie['path']) !== 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Exception.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * A root exception interface for all exceptions in phpCAS.
+ *
+ * All exceptions thrown in phpCAS should implement this interface to allow them
+ * to be caught as a category by clients. Each phpCAS exception should extend
+ * an appropriate SPL exception class that best fits its type.
+ *
+ * For example, an InvalidArgumentException in phpCAS should be defined as
+ *
+ * class CAS_InvalidArgumentException
+ * extends InvalidArgumentException
+ * implements CAS_Exception
+ * { }
+ *
+ * This definition allows the CAS_InvalidArgumentException to be caught as either
+ * an InvalidArgumentException or as a CAS_Exception.
+ *
+ * @class CAS_Exception
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ */
+interface CAS_Exception
+{
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/GracefullTerminationException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * An exception for terminatinating execution or to throw for unit testing
+ *
+ * @class CAS_GracefullTerminationException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class CAS_GracefullTerminationException
+extends RuntimeException
+implements CAS_Exception
+{
+
+ /**
+ * Test if exceptions should be thrown or if we should just exit.
+ * In production usage we want to just exit cleanly when prompting the user
+ * for a redirect without filling the error logs with uncaught exceptions.
+ * In unit testing scenarios we cannot exit or we won't be able to continue
+ * with our tests.
+ *
+ * @param string $message Message Text
+ * @param int $code Error code
+ *
+ * @return self
+ */
+ public function __construct ($message = 'Terminate Gracefully', $code = 0)
+ {
+ // Exit cleanly to avoid filling up the logs with uncaught exceptions.
+ if (self::$_exitWhenThrown) {
+ exit;
+ } else {
+ // Throw exceptions to allow unit testing to continue;
+ parent::__construct($message, $code);
+ }
+ }
+
+ private static $_exitWhenThrown = true;
+ /**
+ * Force phpcas to thow Exceptions instead of calling exit()
+ * Needed for unit testing. Generally shouldn't be used in production due to
+ * an increase in Apache error logging if CAS_GracefulTerminiationExceptions
+ * are not caught and handled.
+ *
+ * @return void
+ */
+ public static function throwInsteadOfExiting()
+ {
+ self::$_exitWhenThrown = false;
+ }
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/InvalidArgumentException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Exception that denotes invalid arguments were passed.
+ *
+ * @class CAS_InvalidArgumentException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_InvalidArgumentException
+extends InvalidArgumentException
+implements CAS_Exception
+{
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/Catalan.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Catalan language class
+ *
+ * @class CAS_Languages_Catalan
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_Catalan implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'usant servidor';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'Autentificació CAS necessària!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'Sortida de CAS necessària!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click <a href="%s">aquí</a> per a continuar.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'Autentificació CAS fallida!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>No estàs autentificat.</p><p>Pots tornar a intentar-ho fent click <a href="%s">aquí</a>.</p><p>Si el problema persisteix hauría de contactar amb l\'<a href="mailto:%s">administrador d\'aquest llocc</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'El servei `<b>%s</b>\' no està disponible (<b>%s</b>).';
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/ChineseSimplified.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>, Phy25 <caslang@phy25.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Chinese Simplified language class
+ *
+ * @class CAS_Languages_ChineseSimplified
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>, Phy25 <caslang@phy25.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_ChineseSimplified implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return '连接的服务器';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return '请进行 CAS 认证!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return '请进行 CAS 登出!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return '你正被重定向到 CAS 服务器。<a href="%s">点击这里</a>继续。';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CAS 认证失败!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>你没有成功登录。</p><p>你可以<a href="%s">点击这里重新登录</a>。</p><p>如果问题依然存在,请<a href="mailto:%s">联系本站管理员</a>。</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return '服务器 <b>%s</b> 不可用(<b>%s</b>)。';
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/English.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * English language class
+ *
+ * @class CAS_Languages_English
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_English implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'using server';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'CAS Authentication wanted!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'CAS logout wanted!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'You should already have been redirected to the CAS server. Click <a href="%s">here</a> to continue.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CAS Authentication failed!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>You were not authenticated.</p><p>You may submit your request again by clicking <a href="%s">here</a>.</p><p>If the problem persists, you may contact <a href="mailto:%s">the administrator of this site</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'The service `<b>%s</b>\' is not available (<b>%s</b>).';
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/French.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * French language class
+ *
+ * @class CAS_Languages_French
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_French implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'utilisant le serveur';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'Authentication CAS nécessaire !';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'Déconnexion demandée !';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Vous auriez du etre redirigé(e) vers le serveur CAS. Cliquez <a href="%s">ici</a> pour continuer.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'Authentification CAS infructueuse !';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>Vous n\'avez pas été authentifié(e).</p><p>Vous pouvez soumettre votre requete à nouveau en cliquant <a href="%s">ici</a>.</p><p>Si le problème persiste, vous pouvez contacter <a href="mailto:%s">l\'administrateur de ce site</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'Le service `<b>%s</b>\' est indisponible (<b>%s</b>)';
+ }
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/German.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Henrik Genssen <hg@mediafactory.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * German language class
+ *
+ * @class CAS_Languages_German
+ * @category Authentication
+ * @package PhpCAS
+ * @author Henrik Genssen <hg@mediafactory.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_German implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'via Server';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'CAS Authentifizierung erforderlich!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'CAS Abmeldung!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie <a href="%s">hier</a> um fortzufahren.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CAS Anmeldung fehlgeschlagen!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>Sie wurden nicht angemeldet.</p><p>Um es erneut zu versuchen klicken Sie <a href="%s">hier</a>.</p><p>Wenn das Problem bestehen bleibt, kontaktieren Sie den <a href="mailto:%s">Administrator</a> dieser Seite.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'Der Dienst `<b>%s</b>\' ist nicht verfügbar (<b>%s</b>).';
+ }
+}
+
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/Greek.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Vangelis Haniotakis <haniotak@ucnet.uoc.gr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Greek language class
+ *
+ * @class CAS_Languages_Greek
+ * @category Authentication
+ * @package PhpCAS
+ * @author Vangelis Haniotakis <haniotak@ucnet.uoc.gr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_Greek implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'χρησιμοποιείται ο εξυπηρετητής';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'Απαιτείται η ταυτοποίηση CAS!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'Απαιτείται η αποσύνδεση από CAS!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Θα έπρεπε να είχατε ανακατευθυνθεί στον εξυπηρετητή CAS. Κάντε κλίκ <a href="%s">εδώ</a> για να συνεχίσετε.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'Η ταυτοποίηση CAS απέτυχε!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>Δεν ταυτοποιηθήκατε.</p><p>Μπορείτε να ξαναπροσπαθήσετε, κάνοντας κλίκ <a href="%s">εδώ</a>.</p><p>Εαν το πρόβλημα επιμείνει, ελάτε σε επαφή με τον <a href="mailto:%s">διαχειριστή</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'Η υπηρεσία `<b>%s</b>\' δεν είναι διαθέσιμη (<b>%s</b>).';
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/Japanese.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author fnorif <fnorif@yahoo.co.jp>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Japanese language class. Now Encoding is UTF-8.
+ *
+ * @class CAS_Languages_Japanese
+ * @category Authentication
+ * @package PhpCAS
+ * @author fnorif <fnorif@yahoo.co.jp>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ **/
+class CAS_Languages_Japanese implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'サーバーを使っています。';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'CASによる認証を行います。';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'CASからログアウトします!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'CASサーバに行く必要があります。自動的に転送されない場合は <a href="%s">こちら</a> をクリックして続行します。';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CASによる認証に失敗しました。';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>認証できませんでした。</p><p>もう一度リクエストを送信する場合は<a href="%s">こちら</a>をクリック。</p><p>問題が解決しない場合は <a href="mailto:%s">このサイトの管理者</a>に問い合わせてください。</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'サービス `<b>%s</b>\' は利用できません (<b>%s</b>)。';
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/LanguageInterface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Language Interface class for all internationalization files
+ *
+ * @class CAS_Languages_LanguageInterface
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+
+interface CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer();
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted();
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout();
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected();
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed();
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated();
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable();
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Language/Spanish.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Spanish language class
+ *
+ * @class CAS_Languages_Spanish
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_Spanish implements CAS_Languages_LanguageInterface
+{
+
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'usando servidor';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return '¡Autentificación CAS necesaria!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return '¡Salida CAS necesaria!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Ya debería haber sido redireccionado al servidor CAS. Haga click <a href="%s">aquí</a> para continuar.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return '¡Autentificación CAS fallida!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>No estás autentificado.</p><p>Puedes volver a intentarlo haciendo click <a href="%s">aquí</a>.</p><p>Si el problema persiste debería contactar con el <a href="mailto:%s">administrador de este sitio</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'El servicio `<b>%s</b>\' no está disponible (<b>%s</b>).';
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * PHP Version 5
+ *
+ * @file CAS/OutOfSequenceBeforeAuthenticationCallException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class defines Exceptions that should be thrown when the sequence of
+ * operations is invalid. In this case it should be thrown when an
+ * authentication call has not yet happened.
+ *
+ * @class CAS_OutOfSequenceBeforeAuthenticationCallException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_OutOfSequenceBeforeAuthenticationCallException
+extends CAS_OutOfSequenceException
+implements CAS_Exception
+{
+ /**
+ * Return standard error meessage
+ *
+ * @return void
+ */
+ public function __construct ()
+ {
+ parent::__construct('An authentication call hasn\'t happened yet.');
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * PHP Version 5
+ *
+ * @file CAS/OutOfSequenceBeforeClientException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class defines Exceptions that should be thrown when the sequence of
+ * operations is invalid. In this case it should be thrown when the client() or
+ * proxy() call has not yet happened and no client or proxy object exists.
+ *
+ * @class CAS_OutOfSequenceBeforeClientException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_OutOfSequenceBeforeClientException
+extends CAS_OutOfSequenceException
+implements CAS_Exception
+{
+ /**
+ * Return standard error message
+ *
+ * @return void
+ */
+ public function __construct ()
+ {
+ parent::__construct(
+ 'this method cannot be called before phpCAS::client() or phpCAS::proxy()'
+ );
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * PHP Version 5
+ *
+ * @file CAS/OutOfSequenceBeforeProxyException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class defines Exceptions that should be thrown when the sequence of
+ * operations is invalid. In this case it should be thrown when the proxy() call
+ * has not yet happened and no proxy object exists.
+ *
+ * @class CAS_OutOfSequenceBeforeProxyException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Joachim Fritschi <jfritschi@freenet.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_OutOfSequenceBeforeProxyException
+extends CAS_OutOfSequenceException
+implements CAS_Exception
+{
+
+ /**
+ * Return standard error message
+ *
+ * @return void
+ */
+ public function __construct ()
+ {
+ parent::__construct(
+ 'this method cannot be called before phpCAS::proxy()'
+ );
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * PHP Version 5
+ *
+ * @file CAS/OutOfSequenceException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class defines Exceptions that should be thrown when the sequence of
+ * operations is invalid. Examples are:
+ * - Requesting the response before executing a request.
+ * - Changing the URL of a request after executing the request.
+ *
+ * @class CAS_OutOfSequenceException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_OutOfSequenceException
+extends BadMethodCallException
+implements CAS_Exception
+{
+
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/PGTStorage/AbstractStorage.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Basic class for PGT storage
+ * The CAS_PGTStorage_AbstractStorage class is a generic class for PGT storage.
+ * This class should not be instanciated itself but inherited by specific PGT
+ * storage classes.
+ *
+ * @class CAS_PGTStorage_AbstractStorage
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @ingroup internalPGTStorage
+ */
+
+abstract class CAS_PGTStorage_AbstractStorage
+{
+ /**
+ * @addtogroup internalPGTStorage
+ * @{
+ */
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+
+ /**
+ * The constructor of the class, should be called only by inherited classes.
+ *
+ * @param CAS_Client $cas_parent the CAS _client instance that creates the
+ * current object.
+ *
+ * @return void
+ *
+ * @protected
+ */
+ function __construct($cas_parent)
+ {
+ phpCAS::traceBegin();
+ if ( !$cas_parent->isProxy() ) {
+ phpCAS::error(
+ 'defining PGT storage makes no sense when not using a CAS proxy'
+ );
+ }
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * This virtual method returns an informational string giving the type of storage
+ * used by the object (used for debugging purposes).
+ *
+ * @return string
+ *
+ * @public
+ */
+ function getStorageType()
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ /**
+ * This virtual method returns an informational string giving informations on the
+ * parameters of the storage.(used for debugging purposes).
+ *
+ * @return string
+ *
+ * @public
+ */
+ function getStorageInfo()
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ // ########################################################################
+ // ERROR HANDLING
+ // ########################################################################
+
+ /**
+ * string used to store an error message. Written by
+ * PGTStorage::setErrorMessage(), read by PGTStorage::getErrorMessage().
+ *
+ * @hideinitializer
+ * @deprecated not used.
+ */
+ var $_error_message=false;
+
+ /**
+ * This method sets en error message, which can be read later by
+ * PGTStorage::getErrorMessage().
+ *
+ * @param string $error_message an error message
+ *
+ * @return void
+ *
+ * @deprecated not used.
+ */
+ function setErrorMessage($error_message)
+ {
+ $this->_error_message = $error_message;
+ }
+
+ /**
+ * This method returns an error message set by PGTStorage::setErrorMessage().
+ *
+ * @return string an error message when set by PGTStorage::setErrorMessage(), FALSE
+ * otherwise.
+ *
+ * @deprecated not used.
+ */
+ function getErrorMessage()
+ {
+ return $this->_error_message;
+ }
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * a boolean telling if the storage has already been initialized. Written by
+ * PGTStorage::init(), read by PGTStorage::isInitialized().
+ *
+ * @hideinitializer
+ */
+ var $_initialized = false;
+
+ /**
+ * This method tells if the storage has already been intialized.
+ *
+ * @return bool
+ *
+ * @protected
+ */
+ function isInitialized()
+ {
+ return $this->_initialized;
+ }
+
+ /**
+ * This virtual method initializes the object.
+ *
+ * @return void
+ */
+ function init()
+ {
+ $this->_initialized = true;
+ }
+
+ // ########################################################################
+ // PGT I/O
+ // ########################################################################
+
+ /**
+ * This virtual method stores a PGT and its corresponding PGT Iuo.
+ *
+ * @param string $pgt the PGT
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ *
+ * @note Should never be called.
+ *
+ */
+ function write($pgt,$pgt_iou)
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ /**
+ * This virtual method reads a PGT corresponding to a PGT Iou and deletes
+ * the corresponding storage entry.
+ *
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return string
+ *
+ * @note Should never be called.
+ */
+ function read($pgt_iou)
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ /** @} */
+
+}
+
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/PGTStorage/Db.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Daniel Frett <daniel.frett@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+define('CAS_PGT_STORAGE_DB_DEFAULT_TABLE', 'cas_pgts');
+
+/**
+ * Basic class for PGT database storage
+ * The CAS_PGTStorage_Db class is a class for PGT database storage.
+ *
+ * @class CAS_PGTStorage_Db
+ * @category Authentication
+ * @package PhpCAS
+ * @author Daniel Frett <daniel.frett@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @ingroup internalPGTStorageDb
+ */
+
+class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage
+{
+ /**
+ * @addtogroup internalCAS_PGTStorageDb
+ * @{
+ */
+
+ /**
+ * the PDO object to use for database interactions
+ */
+ private $_pdo;
+
+ /**
+ * This method returns the PDO object to use for database interactions.
+ *
+ * @return PDO object
+ */
+ private function _getPdo()
+ {
+ return $this->_pdo;
+ }
+
+ /**
+ * database connection options to use when creating a new PDO object
+ */
+ private $_dsn;
+ private $_username;
+ private $_password;
+ private $_driver_options;
+
+ /**
+ * @var string the table to use for storing/retrieving pgt's
+ */
+ private $_table;
+
+ /**
+ * This method returns the table to use when storing/retrieving PGT's
+ *
+ * @return string the name of the pgt storage table.
+ */
+ private function _getTable()
+ {
+ return $this->_table;
+ }
+
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * This method returns an informational string giving the type of storage
+ * used by the object (used for debugging purposes).
+ *
+ * @return string an informational string.
+ */
+ public function getStorageType()
+ {
+ return "db";
+ }
+
+ /**
+ * This method returns an informational string giving informations on the
+ * parameters of the storage.(used for debugging purposes).
+ *
+ * @return string an informational string.
+ * @public
+ */
+ public function getStorageInfo()
+ {
+ return 'table=`'.$this->_getTable().'\'';
+ }
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+
+ /**
+ * The class constructor.
+ *
+ * @param CAS_Client $cas_parent the CAS_Client instance that creates
+ * the object.
+ * @param string $dsn_or_pdo a dsn string to use for creating a PDO
+ * object or a PDO object
+ * @param string $username the username to use when connecting to
+ * the database
+ * @param string $password the password to use when connecting to
+ * the database
+ * @param string $table the table to use for storing and
+ * retrieving PGT's
+ * @param string $driver_options any driver options to use when
+ * connecting to the database
+ */
+ public function __construct(
+ $cas_parent, $dsn_or_pdo, $username='', $password='', $table='',
+ $driver_options=null
+ ) {
+ phpCAS::traceBegin();
+ // call the ancestor's constructor
+ parent::__construct($cas_parent);
+
+ // set default values
+ if ( empty($table) ) {
+ $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE;
+ }
+ if ( !is_array($driver_options) ) {
+ $driver_options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
+ }
+
+ // store the specified parameters
+ if ($dsn_or_pdo instanceof PDO) {
+ $this->_pdo = $dsn_or_pdo;
+ } else {
+ $this->_dsn = $dsn_or_pdo;
+ $this->_username = $username;
+ $this->_password = $password;
+ $this->_driver_options = $driver_options;
+ }
+
+ // store the table name
+ $this->_table = $table;
+
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * This method is used to initialize the storage. Halts on error.
+ *
+ * @return void
+ */
+ public function init()
+ {
+ phpCAS::traceBegin();
+ // if the storage has already been initialized, return immediatly
+ if ($this->isInitialized()) {
+ return;
+ }
+
+ // initialize the base object
+ parent::init();
+
+ // create the PDO object if it doesn't exist already
+ if (!($this->_pdo instanceof PDO)) {
+ try {
+ $this->_pdo = new PDO(
+ $this->_dsn, $this->_username, $this->_password,
+ $this->_driver_options
+ );
+ }
+ catch(PDOException $e) {
+ phpCAS::error('Database connection error: ' . $e->getMessage());
+ }
+ }
+
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // PDO database interaction
+ // ########################################################################
+
+ /**
+ * attribute that stores the previous error mode for the PDO handle while
+ * processing a transaction
+ */
+ private $_errMode;
+
+ /**
+ * This method will enable the Exception error mode on the PDO object
+ *
+ * @return void
+ */
+ private function _setErrorMode()
+ {
+ // get PDO object and enable exception error mode
+ $pdo = $this->_getPdo();
+ $this->_errMode = $pdo->getAttribute(PDO::ATTR_ERRMODE);
+ $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ }
+
+ /**
+ * this method will reset the error mode on the PDO object
+ *
+ * @return void
+ */
+ private function _resetErrorMode()
+ {
+ // get PDO object and reset the error mode to what it was originally
+ $pdo = $this->_getPdo();
+ $pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_errMode);
+ }
+
+ // ########################################################################
+ // database queries
+ // ########################################################################
+ // these queries are potentially unsafe because the person using this library
+ // can set the table to use, but there is no reliable way to escape SQL
+ // fieldnames in PDO yet
+
+ /**
+ * This method returns the query used to create a pgt storage table
+ *
+ * @return string the create table SQL, no bind params in query
+ */
+ protected function createTableSql()
+ {
+ return 'CREATE TABLE ' . $this->_getTable()
+ . ' (pgt_iou VARCHAR(255) NOT NULL PRIMARY KEY, pgt VARCHAR(255) NOT NULL)';
+ }
+
+ /**
+ * This method returns the query used to store a pgt
+ *
+ * @return string the store PGT SQL, :pgt and :pgt_iou are the bind params contained
+ * in the query
+ */
+ protected function storePgtSql()
+ {
+ return 'INSERT INTO ' . $this->_getTable()
+ . ' (pgt_iou, pgt) VALUES (:pgt_iou, :pgt)';
+ }
+
+ /**
+ * This method returns the query used to retrieve a pgt. the first column
+ * of the first row should contain the pgt
+ *
+ * @return string the retrieve PGT SQL, :pgt_iou is the only bind param contained
+ * in the query
+ */
+ protected function retrievePgtSql()
+ {
+ return 'SELECT pgt FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
+ }
+
+ /**
+ * This method returns the query used to delete a pgt.
+ *
+ * @return string the delete PGT SQL, :pgt_iou is the only bind param contained in
+ * the query
+ */
+ protected function deletePgtSql()
+ {
+ return 'DELETE FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
+ }
+
+ // ########################################################################
+ // PGT I/O
+ // ########################################################################
+
+ /**
+ * This method creates the database table used to store pgt's and pgtiou's
+ *
+ * @return void
+ */
+ public function createTable()
+ {
+ phpCAS::traceBegin();
+
+ // initialize this PGTStorage object if it hasn't been initialized yet
+ if ( !$this->isInitialized() ) {
+ $this->init();
+ }
+
+ // initialize the PDO object for this method
+ $pdo = $this->_getPdo();
+ $this->_setErrorMode();
+
+ try {
+ $pdo->beginTransaction();
+
+ $query = $pdo->query($this->createTableSQL());
+ $query->closeCursor();
+
+ $pdo->commit();
+ }
+ catch(PDOException $e) {
+ // attempt rolling back the transaction before throwing a phpCAS error
+ try {
+ $pdo->rollBack();
+ }
+ catch(PDOException $e) {
+ }
+ phpCAS::error('error creating PGT storage table: ' . $e->getMessage());
+ }
+
+ // reset the PDO object
+ $this->_resetErrorMode();
+
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method stores a PGT and its corresponding PGT Iou in the database.
+ * Echoes a warning on error.
+ *
+ * @param string $pgt the PGT
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ */
+ public function write($pgt, $pgt_iou)
+ {
+ phpCAS::traceBegin();
+
+ // initialize the PDO object for this method
+ $pdo = $this->_getPdo();
+ $this->_setErrorMode();
+
+ try {
+ $pdo->beginTransaction();
+
+ $query = $pdo->prepare($this->storePgtSql());
+ $query->bindValue(':pgt', $pgt, PDO::PARAM_STR);
+ $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
+ $query->execute();
+ $query->closeCursor();
+
+ $pdo->commit();
+ }
+ catch(PDOException $e) {
+ // attempt rolling back the transaction before throwing a phpCAS error
+ try {
+ $pdo->rollBack();
+ }
+ catch(PDOException $e) {
+ }
+ phpCAS::error('error writing PGT to database: ' . $e->getMessage());
+ }
+
+ // reset the PDO object
+ $this->_resetErrorMode();
+
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method reads a PGT corresponding to a PGT Iou and deletes the
+ * corresponding db entry.
+ *
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return string|false the corresponding PGT, or FALSE on error
+ */
+ public function read($pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $pgt = false;
+
+ // initialize the PDO object for this method
+ $pdo = $this->_getPdo();
+ $this->_setErrorMode();
+
+ try {
+ $pdo->beginTransaction();
+
+ // fetch the pgt for the specified pgt_iou
+ $query = $pdo->prepare($this->retrievePgtSql());
+ $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
+ $query->execute();
+ $pgt = $query->fetchColumn(0);
+ $query->closeCursor();
+
+ // delete the specified pgt_iou from the database
+ $query = $pdo->prepare($this->deletePgtSql());
+ $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
+ $query->execute();
+ $query->closeCursor();
+
+ $pdo->commit();
+ }
+ catch(PDOException $e) {
+ // attempt rolling back the transaction before throwing a phpCAS error
+ try {
+ $pdo->rollBack();
+ }
+ catch(PDOException $e) {
+ }
+ phpCAS::trace('error reading PGT from database: ' . $e->getMessage());
+ }
+
+ // reset the PDO object
+ $this->_resetErrorMode();
+
+ phpCAS::traceEnd();
+ return $pgt;
+ }
+
+ /** @} */
+
+}
+
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/PGTStorage/AbstractStorage.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * The CAS_PGTStorage_File class is a class for PGT file storage. An instance of
+ * this class is returned by CAS_Client::SetPGTStorageFile().
+ *
+ * @class CAS_PGTStorage_File
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ *
+ * @ingroup internalPGTStorageFile
+ */
+
+class CAS_PGTStorage_File extends CAS_PGTStorage_AbstractStorage
+{
+ /**
+ * @addtogroup internalPGTStorageFile
+ * @{
+ */
+
+ /**
+ * a string telling where PGT's should be stored on the filesystem. Written by
+ * PGTStorageFile::PGTStorageFile(), read by getPath().
+ *
+ * @private
+ */
+ var $_path;
+
+ /**
+ * This method returns the name of the directory where PGT's should be stored
+ * on the filesystem.
+ *
+ * @return string the name of a directory (with leading and trailing '/')
+ *
+ * @private
+ */
+ function getPath()
+ {
+ return $this->_path;
+ }
+
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * This method returns an informational string giving the type of storage
+ * used by the object (used for debugging purposes).
+ *
+ * @return string an informational string.
+ * @public
+ */
+ function getStorageType()
+ {
+ return "file";
+ }
+
+ /**
+ * This method returns an informational string giving informations on the
+ * parameters of the storage.(used for debugging purposes).
+ *
+ * @return string an informational string.
+ * @public
+ */
+ function getStorageInfo()
+ {
+ return 'path=`'.$this->getPath().'\'';
+ }
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+
+ /**
+ * The class constructor, called by CAS_Client::SetPGTStorageFile().
+ *
+ * @param CAS_Client $cas_parent the CAS_Client instance that creates the object.
+ * @param string $path the path where the PGT's should be stored
+ *
+ * @return void
+ *
+ * @public
+ */
+ function __construct($cas_parent,$path)
+ {
+ phpCAS::traceBegin();
+ // call the ancestor's constructor
+ parent::__construct($cas_parent);
+
+ if (empty($path)) {
+ $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH;
+ }
+ // check that the path is an absolute path
+ if (getenv("OS")=="Windows_NT" || strtoupper(substr(PHP_OS,0,3)) == 'WIN') {
+
+ if (!preg_match('`^[a-zA-Z]:`', $path)) {
+ phpCAS::error('an absolute path is needed for PGT storage to file');
+ }
+
+ } else {
+
+ if ( $path[0] != '/' ) {
+ phpCAS::error('an absolute path is needed for PGT storage to file');
+ }
+
+ // store the path (with a leading and trailing '/')
+ $path = preg_replace('|[/]*$|', '/', $path);
+ $path = preg_replace('|^[/]*|', '/', $path);
+ }
+
+ $this->_path = $path;
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * This method is used to initialize the storage. Halts on error.
+ *
+ * @return void
+ * @public
+ */
+ function init()
+ {
+ phpCAS::traceBegin();
+ // if the storage has already been initialized, return immediatly
+ if ($this->isInitialized()) {
+ return;
+ }
+ // call the ancestor's method (mark as initialized)
+ parent::init();
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // PGT I/O
+ // ########################################################################
+
+ /**
+ * This method returns the filename corresponding to a PGT Iou.
+ *
+ * @param string $pgt_iou the PGT iou.
+ *
+ * @return string a filename
+ * @private
+ */
+ function getPGTIouFilename($pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $filename = $this->getPath()."phpcas-".hash("sha256", $pgt_iou);
+// $filename = $this->getPath().$pgt_iou.'.plain';
+ phpCAS::trace("Sha256 filename:" . $filename);
+ phpCAS::traceEnd();
+ return $filename;
+ }
+
+ /**
+ * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a
+ * warning on error.
+ *
+ * @param string $pgt the PGT
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ *
+ * @public
+ */
+ function write($pgt,$pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $fname = $this->getPGTIouFilename($pgt_iou);
+ if (!file_exists($fname)) {
+ touch($fname);
+ // Chmod will fail on windows
+ @chmod($fname, 0600);
+ if ($f=fopen($fname, "w")) {
+ if (fputs($f, $pgt) === false) {
+ phpCAS::error('could not write PGT to `'.$fname.'\'');
+ }
+ phpCAS::trace('Successful write of PGT to `'.$fname.'\'');
+ fclose($f);
+ } else {
+ phpCAS::error('could not open `'.$fname.'\'');
+ }
+ } else {
+ phpCAS::error('File exists: `'.$fname.'\'');
+ }
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method reads a PGT corresponding to a PGT Iou and deletes the
+ * corresponding file.
+ *
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return string|false the corresponding PGT, or FALSE on error
+ *
+ * @public
+ */
+ function read($pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $pgt = false;
+ $fname = $this->getPGTIouFilename($pgt_iou);
+ if (file_exists($fname)) {
+ if (!($f=fopen($fname, "r"))) {
+ phpCAS::error('could not open `'.$fname.'\'');
+ } else {
+ if (($pgt=fgets($f)) === false) {
+ phpCAS::error('could not read PGT from `'.$fname.'\'');
+ }
+ phpCAS::trace('Successful read of PGT to `'.$fname.'\'');
+ fclose($f);
+ }
+ // delete the PGT file
+ @unlink($fname);
+ } else {
+ phpCAS::error('No such file `'.$fname.'\'');
+ }
+ phpCAS::traceEnd($pgt);
+ return $pgt;
+ }
+
+ /** @} */
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines methods that allow proxy-authenticated service handlers
+ * to interact with phpCAS.
+ *
+ * Proxy service handlers must implement this interface as well as call
+ * phpCAS::initializeProxiedService($this) at some point in their implementation.
+ *
+ * While not required, proxy-authenticated service handlers are encouraged to
+ * implement the CAS_ProxiedService_Testable interface to facilitate unit testing.
+ *
+ * @class CAS_ProxiedService
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+interface CAS_ProxiedService
+{
+
+ /**
+ * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
+ *
+ * @return string
+ * @throws Exception If no service url is available.
+ */
+ public function getServiceUrl ();
+
+ /**
+ * Register a proxy ticket with the ProxiedService that it can use when
+ * making requests.
+ *
+ * @param string $proxyTicket Proxy ticket string
+ *
+ * @return void
+ * @throws InvalidArgumentException If the $proxyTicket is invalid.
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized/set.
+ */
+ public function setProxyTicket ($proxyTicket);
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Abstract.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class implements common methods for ProxiedService implementations included
+ * with phpCAS.
+ *
+ * @class CAS_ProxiedService_Abstract
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+abstract class CAS_ProxiedService_Abstract
+implements CAS_ProxiedService, CAS_ProxiedService_Testable
+{
+
+ /**
+ * The proxy ticket that can be used when making service requests.
+ * @var string $_proxyTicket;
+ */
+ private $_proxyTicket;
+
+ /**
+ * Register a proxy ticket with the Proxy that it can use when making requests.
+ *
+ * @param string $proxyTicket proxy ticket
+ *
+ * @return void
+ * @throws InvalidArgumentException If the $proxyTicket is invalid.
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized/set.
+ */
+ public function setProxyTicket ($proxyTicket)
+ {
+ if (empty($proxyTicket)) {
+ throw new CAS_InvalidArgumentException(
+ 'Trying to initialize with an empty proxy ticket.'
+ );
+ }
+ if (!empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException(
+ 'Already initialized, cannot change the proxy ticket.'
+ );
+ }
+ $this->_proxyTicket = $proxyTicket;
+ }
+
+ /**
+ * Answer the proxy ticket to be used when making requests.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before a proxy ticket has
+ * already been initialized/set.
+ */
+ protected function getProxyTicket ()
+ {
+ if (empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException(
+ 'No proxy ticket yet. Call $this->initializeProxyTicket() to aquire the proxy ticket.'
+ );
+ }
+
+ return $this->_proxyTicket;
+ }
+
+ /**
+ * @var CAS_Client $_casClient;
+ */
+ private $_casClient;
+
+ /**
+ * Use a particular CAS_Client->initializeProxiedService() rather than the
+ * static phpCAS::initializeProxiedService().
+ *
+ * This method should not be called in standard operation, but is needed for unit
+ * testing.
+ *
+ * @param CAS_Client $casClient cas client
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized/set.
+ */
+ public function setCasClient (CAS_Client $casClient)
+ {
+ if (!empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException(
+ 'Already initialized, cannot change the CAS_Client.'
+ );
+ }
+
+ $this->_casClient = $casClient;
+ }
+
+ /**
+ * Fetch our proxy ticket.
+ *
+ * Descendent classes should call this method once their service URL is available
+ * to initialize their proxy ticket.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized.
+ */
+ protected function initializeProxyTicket()
+ {
+ if (!empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException(
+ 'Already initialized, cannot initialize again.'
+ );
+ }
+ // Allow usage of a particular CAS_Client for unit testing.
+ if (empty($this->_casClient)) {
+ phpCAS::initializeProxiedService($this);
+ } else {
+ $this->_casClient->initializeProxiedService($this);
+ }
+ }
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Exception.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * An Exception for problems communicating with a proxied service.
+ *
+ * @class CAS_ProxiedService_Exception
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxiedService_Exception
+extends Exception
+implements CAS_Exception
+{
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Http.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines methods that clients should use for configuring, sending,
+ * and receiving proxied HTTP requests.
+ *
+ * @class CAS_ProxiedService_Http
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+interface CAS_ProxiedService_Http
+{
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url Url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url);
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ();
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ();
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ();
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Http/Abstract.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class implements common methods for ProxiedService implementations included
+ * with phpCAS.
+ *
+ * @class CAS_ProxiedService_Http_Abstract
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+abstract class CAS_ProxiedService_Http_Abstract extends
+CAS_ProxiedService_Abstract implements CAS_ProxiedService_Http
+{
+ /**
+ * The HTTP request mechanism talking to the target service.
+ *
+ * @var CAS_Request_RequestInterface $requestHandler
+ */
+ protected $requestHandler;
+
+ /**
+ * The storage mechanism for cookies set by the target service.
+ *
+ * @var CAS_CookieJar $_cookieJar
+ */
+ private $_cookieJar;
+
+ /**
+ * Constructor.
+ *
+ * @param CAS_Request_RequestInterface $requestHandler request handler object
+ * @param CAS_CookieJar $cookieJar cookieJar object
+ *
+ * @return void
+ */
+ public function __construct(CAS_Request_RequestInterface $requestHandler,
+ CAS_CookieJar $cookieJar
+ ) {
+ $this->requestHandler = $requestHandler;
+ $this->_cookieJar = $cookieJar;
+ }
+
+ /**
+ * The target service url.
+ * @var string $_url;
+ */
+ private $_url;
+
+ /**
+ * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
+ *
+ * @return string
+ * @throws Exception If no service url is available.
+ */
+ public function getServiceUrl()
+ {
+ if (empty($this->_url)) {
+ throw new CAS_ProxiedService_Exception(
+ 'No URL set via ' . get_class($this) . '->setUrl($url).'
+ );
+ }
+
+ return $this->_url;
+ }
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl($url)
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot set the URL, request already sent.'
+ );
+ }
+ if (!is_string($url)) {
+ throw new CAS_InvalidArgumentException('$url must be a string.');
+ }
+
+ $this->_url = $url;
+ }
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
+ * The code of the Exception will be one of:
+ * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_FAILURE
+ * @throws CAS_ProxiedService_Exception If there is a failure sending the
+ * request to the target service.
+ */
+ public function send()
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot send, request already sent.'
+ );
+ }
+
+ phpCAS::traceBegin();
+
+ // Get our proxy ticket and append it to our URL.
+ $this->initializeProxyTicket();
+ $url = $this->getServiceUrl();
+ if (strstr($url, '?') === false) {
+ $url = $url . '?ticket=' . $this->getProxyTicket();
+ } else {
+ $url = $url . '&ticket=' . $this->getProxyTicket();
+ }
+
+ try {
+ $this->makeRequest($url);
+ } catch (Exception $e) {
+ phpCAS::traceEnd();
+ throw $e;
+ }
+ }
+
+ /**
+ * Indicator of the number of requests (including redirects performed.
+ *
+ * @var int $_numRequests;
+ */
+ private $_numRequests = 0;
+
+ /**
+ * The response headers.
+ *
+ * @var array $_responseHeaders;
+ */
+ private $_responseHeaders = array();
+
+ /**
+ * The response status code.
+ *
+ * @var int $_responseStatusCode;
+ */
+ private $_responseStatusCode = '';
+
+ /**
+ * The response headers.
+ *
+ * @var string $_responseBody;
+ */
+ private $_responseBody = '';
+
+ /**
+ * Build and perform a request, following redirects
+ *
+ * @param string $url url for the request
+ *
+ * @return void
+ * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
+ * The code of the Exception will be one of:
+ * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_FAILURE
+ * @throws CAS_ProxiedService_Exception If there is a failure sending the
+ * request to the target service.
+ */
+ protected function makeRequest($url)
+ {
+ // Verify that we are not in a redirect loop
+ $this->_numRequests++;
+ if ($this->_numRequests > 4) {
+ $message = 'Exceeded the maximum number of redirects (3) in proxied service request.';
+ phpCAS::trace($message);
+ throw new CAS_ProxiedService_Exception($message);
+ }
+
+ // Create a new request.
+ $request = clone $this->requestHandler;
+ $request->setUrl($url);
+
+ // Add any cookies to the request.
+ $request->addCookies($this->_cookieJar->getCookies($url));
+
+ // Add any other parts of the request needed by concrete classes
+ $this->populateRequest($request);
+
+ // Perform the request.
+ phpCAS::trace('Performing proxied service request to \'' . $url . '\'');
+ if (!$request->send()) {
+ $message = 'Could not perform proxied service request to URL`'
+ . $url . '\'. ' . $request->getErrorMessage();
+ phpCAS::trace($message);
+ throw new CAS_ProxiedService_Exception($message);
+ }
+
+ // Store any cookies from the response;
+ $this->_cookieJar->storeCookies($url, $request->getResponseHeaders());
+
+ // Follow any redirects
+ if ($redirectUrl = $this->getRedirectUrl($request->getResponseHeaders())
+ ) {
+ phpCAS::trace('Found redirect:' . $redirectUrl);
+ $this->makeRequest($redirectUrl);
+ } else {
+
+ $this->_responseHeaders = $request->getResponseHeaders();
+ $this->_responseBody = $request->getResponseBody();
+ $this->_responseStatusCode = $request->getResponseStatusCode();
+ }
+ }
+
+ /**
+ * Add any other parts of the request needed by concrete classes
+ *
+ * @param CAS_Request_RequestInterface $request request interface object
+ *
+ * @return void
+ */
+ abstract protected function populateRequest(
+ CAS_Request_RequestInterface $request
+ );
+
+ /**
+ * Answer a redirect URL if a redirect header is found, otherwise null.
+ *
+ * @param array $responseHeaders response header to extract a redirect from
+ *
+ * @return string|null
+ */
+ protected function getRedirectUrl(array $responseHeaders)
+ {
+ // Check for the redirect after authentication
+ foreach ($responseHeaders as $header) {
+ if ( preg_match('/^(Location:|URI:)\s*([^\s]+.*)$/', $header, $matches)
+ ) {
+ return trim(array_pop($matches));
+ }
+ }
+ return null;
+ }
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer true if our request has been sent yet.
+ *
+ * @return bool
+ */
+ protected function hasBeenSent()
+ {
+ return ($this->_numRequests > 0);
+ }
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders()
+ {
+ if (!$this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot access response, request not sent yet.'
+ );
+ }
+
+ return $this->_responseHeaders;
+ }
+
+ /**
+ * Answer HTTP status code of the response
+ *
+ * @return int
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseStatusCode()
+ {
+ if (!$this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot access response, request not sent yet.'
+ );
+ }
+
+ return $this->_responseStatusCode;
+ }
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody()
+ {
+ if (!$this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot access response, request not sent yet.'
+ );
+ }
+
+ return $this->_responseBody;
+ }
+
+ /**
+ * Answer the cookies from the response. This may include cookies set during
+ * redirect responses.
+ *
+ * @return array An array containing cookies. E.g. array('name' => 'val');
+ */
+ public function getCookies()
+ {
+ return $this->_cookieJar->getCookies($this->getServiceUrl());
+ }
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Http/Get.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class is used to make proxied service requests via the HTTP GET method.
+ *
+ * Usage Example:
+ *
+ * try {
+ * $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET);
+ * $service->setUrl('http://www.example.com/path/');
+ * $service->send();
+ * if ($service->getResponseStatusCode() == 200)
+ * return $service->getResponseBody();
+ * else
+ * // The service responded with an error code 404, 500, etc.
+ * throw new Exception('The service responded with an error.');
+ *
+ * } catch (CAS_ProxyTicketException $e) {
+ * if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE)
+ * return "Your login has timed out. You need to log in again.";
+ * else
+ * // Other proxy ticket errors are from bad request format
+ * // (shouldn't happen) or CAS server failure (unlikely)
+ * // so lets just stop if we hit those.
+ * throw $e;
+ * } catch (CAS_ProxiedService_Exception $e) {
+ * // Something prevented the service request from being sent or received.
+ * // We didn't even get a valid error response (404, 500, etc), so this
+ * // might be caused by a network error or a DNS resolution failure.
+ * // We could handle it in some way, but for now we will just stop.
+ * throw $e;
+ * }
+ *
+ * @class CAS_ProxiedService_Http_Get
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxiedService_Http_Get
+extends CAS_ProxiedService_Http_Abstract
+{
+
+ /**
+ * Add any other parts of the request needed by concrete classes
+ *
+ * @param CAS_Request_RequestInterface $request request interface
+ *
+ * @return void
+ */
+ protected function populateRequest (CAS_Request_RequestInterface $request)
+ {
+ // do nothing, since the URL has already been sent and that is our
+ // only data.
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Http/Post.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This class is used to make proxied service requests via the HTTP POST method.
+ *
+ * Usage Example:
+ *
+ * try {
+ * $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_POST);
+ * $service->setUrl('http://www.example.com/path/');
+ * $service->setContentType('text/xml');
+ * $service->setBody('<?xml version="1.0"?'.'><methodCall><methodName>example.search</methodName></methodCall>');
+ * $service->send();
+ * if ($service->getResponseStatusCode() == 200)
+ * return $service->getResponseBody();
+ * else
+ * // The service responded with an error code 404, 500, etc.
+ * throw new Exception('The service responded with an error.');
+ *
+ * } catch (CAS_ProxyTicketException $e) {
+ * if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE)
+ * return "Your login has timed out. You need to log in again.";
+ * else
+ * // Other proxy ticket errors are from bad request format
+ * // (shouldn't happen) or CAS server failure (unlikely) so lets just
+ * // stop if we hit those.
+ * throw $e;
+ * } catch (CAS_ProxiedService_Exception $e) {
+ * // Something prevented the service request from being sent or received.
+ * // We didn't even get a valid error response (404, 500, etc), so this
+ * // might be caused by a network error or a DNS resolution failure.
+ * // We could handle it in some way, but for now we will just stop.
+ * throw $e;
+ * }
+ *
+ * @class CAS_ProxiedService_Http_Post
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxiedService_Http_Post
+extends CAS_ProxiedService_Http_Abstract
+{
+
+ /**
+ * The content-type of this request
+ *
+ * @var string $_contentType
+ */
+ private $_contentType;
+
+ /**
+ * The body of the this request
+ *
+ * @var string $_body
+ */
+ private $_body;
+
+ /**
+ * Set the content type of this POST request.
+ *
+ * @param string $contentType content type
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setContentType ($contentType)
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot set the content type, request already sent.'
+ );
+ }
+
+ $this->_contentType = $contentType;
+ }
+
+ /**
+ * Set the body of this POST request.
+ *
+ * @param string $body body to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setBody ($body)
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot set the body, request already sent.'
+ );
+ }
+
+ $this->_body = $body;
+ }
+
+ /**
+ * Add any other parts of the request needed by concrete classes
+ *
+ * @param CAS_Request_RequestInterface $request request interface class
+ *
+ * @return void
+ */
+ protected function populateRequest (CAS_Request_RequestInterface $request)
+ {
+ if (empty($this->_contentType) && !empty($this->_body)) {
+ throw new CAS_ProxiedService_Exception(
+ "If you pass a POST body, you must specify a content type via "
+ .get_class($this).'->setContentType($contentType).'
+ );
+ }
+
+ $request->makePost();
+ if (!empty($this->_body)) {
+ $request->addHeader('Content-Type: '.$this->_contentType);
+ $request->addHeader('Content-Length: '.strlen($this->_body));
+ $request->setPostBody($this->_body);
+ }
+ }
+
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Imap.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Provides access to a proxy-authenticated IMAP stream
+ *
+ * @class CAS_ProxiedService_Imap
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxiedService_Imap
+extends CAS_ProxiedService_Abstract
+{
+
+ /**
+ * The username to send via imap_open.
+ *
+ * @var string $_username;
+ */
+ private $_username;
+
+ /**
+ * Constructor.
+ *
+ * @param string $username Username
+ *
+ * @return void
+ */
+ public function __construct ($username)
+ {
+ if (!is_string($username) || !strlen($username)) {
+ throw new CAS_InvalidArgumentException('Invalid username.');
+ }
+
+ $this->_username = $username;
+ }
+
+ /**
+ * The target service url.
+ * @var string $_url;
+ */
+ private $_url;
+
+ /**
+ * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
+ *
+ * @return string
+ * @throws Exception If no service url is available.
+ */
+ public function getServiceUrl ()
+ {
+ if (empty($this->_url)) {
+ throw new CAS_ProxiedService_Exception(
+ 'No URL set via '.get_class($this).'->getServiceUrl($url).'
+ );
+ }
+
+ return $this->_url;
+ }
+
+ /*********************************************************
+ * Configure the Stream
+ *********************************************************/
+
+ /**
+ * Set the URL of the service to pass to CAS for proxy-ticket retrieval.
+ *
+ * @param string $url Url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the stream has been opened.
+ */
+ public function setServiceUrl ($url)
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot set the URL, stream already opened.'
+ );
+ }
+ if (!is_string($url) || !strlen($url)) {
+ throw new CAS_InvalidArgumentException('Invalid url.');
+ }
+
+ $this->_url = $url;
+ }
+
+ /**
+ * The mailbox to open. See the $mailbox parameter of imap_open().
+ *
+ * @var string $_mailbox
+ */
+ private $_mailbox;
+
+ /**
+ * Set the mailbox to open. See the $mailbox parameter of imap_open().
+ *
+ * @param string $mailbox Mailbox to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the stream has been opened.
+ */
+ public function setMailbox ($mailbox)
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot set the mailbox, stream already opened.'
+ );
+ }
+ if (!is_string($mailbox) || !strlen($mailbox)) {
+ throw new CAS_InvalidArgumentException('Invalid mailbox.');
+ }
+
+ $this->_mailbox = $mailbox;
+ }
+
+ /**
+ * A bit mask of options to pass to imap_open() as the $options parameter.
+ *
+ * @var int $_options
+ */
+ private $_options = null;
+
+ /**
+ * Set the options for opening the stream. See the $options parameter of
+ * imap_open().
+ *
+ * @param int $options Options for the stream
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the stream has been opened.
+ */
+ public function setOptions ($options)
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot set options, stream already opened.'
+ );
+ }
+ if (!is_int($options)) {
+ throw new CAS_InvalidArgumentException('Invalid options.');
+ }
+
+ $this->_options = $options;
+ }
+
+ /*********************************************************
+ * 2. Open the stream
+ *********************************************************/
+
+ /**
+ * Open the IMAP stream (similar to imap_open()).
+ *
+ * @return resource Returns an IMAP stream on success
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
+ * The code of the Exception will be one of:
+ * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
+ * PHPCAS_SERVICE_PT_FAILURE
+ * @throws CAS_ProxiedService_Exception If there is a failure sending the
+ * request to the target service.
+ */
+ public function open ()
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Stream already opened.');
+ }
+ if (empty($this->_mailbox)) {
+ throw new CAS_ProxiedService_Exception(
+ 'You must specify a mailbox via '.get_class($this)
+ .'->setMailbox($mailbox)'
+ );
+ }
+
+ phpCAS::traceBegin();
+
+ // Get our proxy ticket and append it to our URL.
+ $this->initializeProxyTicket();
+ phpCAS::trace('opening IMAP mailbox `'.$this->_mailbox.'\'...');
+ $this->_stream = @imap_open(
+ $this->_mailbox, $this->_username, $this->getProxyTicket(),
+ $this->_options
+ );
+ if ($this->_stream) {
+ phpCAS::trace('ok');
+ } else {
+ phpCAS::trace('could not open mailbox');
+ // @todo add localization integration.
+ $message = 'IMAP Error: '.$this->_url.' '. var_export(imap_errors(), true);
+ phpCAS::trace($message);
+ throw new CAS_ProxiedService_Exception($message);
+ }
+
+ phpCAS::traceEnd();
+ return $this->_stream;
+ }
+
+ /**
+ * Answer true if our request has been sent yet.
+ *
+ * @return bool
+ */
+ protected function hasBeenOpened ()
+ {
+ return !empty($this->_stream);
+ }
+
+ /*********************************************************
+ * 3. Access the result
+ *********************************************************/
+ /**
+ * The IMAP stream
+ *
+ * @var resource $_stream
+ */
+ private $_stream;
+
+ /**
+ * Answer the IMAP stream
+ *
+ * @return resource
+ * @throws CAS_OutOfSequenceException if stream is not opened yet
+ */
+ public function getStream ()
+ {
+ if (!$this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot access stream, not opened yet.'
+ );
+ }
+ return $this->_stream;
+ }
+
+ /**
+ * CAS_Client::serviceMail() needs to return the proxy ticket for some reason,
+ * so this method provides access to it.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the stream has been
+ * opened.
+ */
+ public function getImapProxyTicket ()
+ {
+ if (!$this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot access errors, stream not opened yet.'
+ );
+ }
+ return $this->getProxyTicket();
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxiedService/Testabel.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines methods that allow proxy-authenticated service handlers
+ * to be tested in unit tests.
+ *
+ * Classes implementing this interface SHOULD store the CAS_Client passed and
+ * initialize themselves with that client rather than via the static phpCAS
+ * method. For example:
+ *
+ * / **
+ * * Fetch our proxy ticket.
+ * * /
+ * protected function initializeProxyTicket() {
+ * // Allow usage of a particular CAS_Client for unit testing.
+ * if (is_null($this->casClient))
+ * phpCAS::initializeProxiedService($this);
+ * else
+ * $this->casClient->initializeProxiedService($this);
+ * }
+ *
+ * @class CAS_ProxiedService_Testabel
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+interface CAS_ProxiedService_Testable
+{
+
+ /**
+ * Use a particular CAS_Client->initializeProxiedService() rather than the
+ * static phpCAS::initializeProxiedService().
+ *
+ * This method should not be called in standard operation, but is needed for unit
+ * testing.
+ *
+ * @param CAS_Client $casClient Cas client object
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized/set.
+ */
+ public function setCasClient (CAS_Client $casClient);
+
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxyChain.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * A normal proxy-chain definition that lists each level of the chain as either
+ * a string or regular expression.
+ *
+ * @class CAS_ProxyChain
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class CAS_ProxyChain
+implements CAS_ProxyChain_Interface
+{
+
+ protected $chain = array();
+
+ /**
+ * A chain is an array of strings or regexp strings that will be matched
+ * against. Regexp will be matched with preg_match and strings will be
+ * matched from the beginning. A string must fully match the beginning of
+ * an proxy url. So you can define a full domain as acceptable or go further
+ * down.
+ * Proxies have to be defined in reverse from the service to the user. If a
+ * user hits service A get proxied via B to service C the list of acceptable
+ * proxies on C would be array(B,A);
+ *
+ * @param array $chain A chain of proxies
+ */
+ public function __construct(array $chain)
+ {
+ // Ensure that we have an indexed array
+ $this->chain = array_values($chain);
+ }
+
+ /**
+ * Match a list of proxies.
+ *
+ * @param array $list The list of proxies in front of this service.
+ *
+ * @return bool
+ */
+ public function matches(array $list)
+ {
+ $list = array_values($list); // Ensure that we have an indexed array
+ if ($this->isSizeValid($list)) {
+ $mismatch = false;
+ foreach ($this->chain as $i => $search) {
+ $proxy_url = $list[$i];
+ if (preg_match('/^\/.*\/[ixASUXu]*$/s', $search)) {
+ if (preg_match($search, $proxy_url)) {
+ phpCAS::trace(
+ "Found regexp " . $search . " matching " . $proxy_url
+ );
+ } else {
+ phpCAS::trace(
+ "No regexp match " . $search . " != " . $proxy_url
+ );
+ $mismatch = true;
+ break;
+ }
+ } else {
+ if (strncasecmp($search, $proxy_url, strlen($search)) == 0) {
+ phpCAS::trace(
+ "Found string " . $search . " matching " . $proxy_url
+ );
+ } else {
+ phpCAS::trace(
+ "No match " . $search . " != " . $proxy_url
+ );
+ $mismatch = true;
+ break;
+ }
+ }
+ }
+ if (!$mismatch) {
+ phpCAS::trace("Proxy chain matches");
+ return true;
+ }
+ } else {
+ phpCAS::trace("Proxy chain skipped: size mismatch");
+ }
+ return false;
+ }
+
+ /**
+ * Validate the size of the the list as compared to our chain.
+ *
+ * @param array $list List of proxies
+ *
+ * @return bool
+ */
+ protected function isSizeValid (array $list)
+ {
+ return (sizeof($this->chain) == sizeof($list));
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxyChain/AllowedList.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+
+/**
+ * ProxyChain is a container for storing chains of valid proxies that can
+ * be used to validate proxied requests to a service
+ *
+ * @class CAS_ProxyChain_AllowedList
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class CAS_ProxyChain_AllowedList
+{
+
+ private $_chains = array();
+
+ /**
+ * Check whether proxies are allowed by configuration
+ *
+ * @return bool
+ */
+ public function isProxyingAllowed()
+ {
+ return (count($this->_chains) > 0);
+ }
+
+ /**
+ * Add a chain of proxies to the list of possible chains
+ *
+ * @param CAS_ProxyChain_Interface $chain A chain of proxies
+ *
+ * @return void
+ */
+ public function allowProxyChain(CAS_ProxyChain_Interface $chain)
+ {
+ $this->_chains[] = $chain;
+ }
+
+ /**
+ * Check if the proxies found in the response match the allowed proxies
+ *
+ * @param array $proxies list of proxies to check
+ *
+ * @return bool whether the proxies match the allowed proxies
+ */
+ public function isProxyListAllowed(array $proxies)
+ {
+ phpCAS::traceBegin();
+ if (empty($proxies)) {
+ phpCAS::trace("No proxies were found in the response");
+ phpCAS::traceEnd(true);
+ return true;
+ } elseif (!$this->isProxyingAllowed()) {
+ phpCAS::trace("Proxies are not allowed");
+ phpCAS::traceEnd(false);
+ return false;
+ } else {
+ $res = $this->contains($proxies);
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+ }
+
+ /**
+ * Validate the proxies from the proxy ticket validation against the
+ * chains that were definded.
+ *
+ * @param array $list List of proxies from the proxy ticket validation.
+ *
+ * @return bool if any chain fully matches the supplied list
+ */
+ public function contains(array $list)
+ {
+ phpCAS::traceBegin();
+ $count = 0;
+ foreach ($this->_chains as $chain) {
+ phpCAS::trace("Checking chain ". $count++);
+ if ($chain->matches($list)) {
+ phpCAS::traceEnd(true);
+ return true;
+ }
+ }
+ phpCAS::trace("No proxy chain matches.");
+ phpCAS::traceEnd(false);
+ return false;
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxyChain/Any.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * A proxy-chain definition that will match any list of proxies.
+ *
+ * Use this class for quick testing or in certain production screnarios you
+ * might want to allow allow any other valid service to proxy your service.
+ *
+ * THIS CLASS IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY
+ * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER
+ * ON THIS SERVICE.
+ *
+ * @class CAS_ProxyChain_Any
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxyChain_Any
+implements CAS_ProxyChain_Interface
+{
+
+ /**
+ * Match a list of proxies.
+ *
+ * @param array $list The list of proxies in front of this service.
+ *
+ * @return bool
+ */
+ public function matches(array $list)
+ {
+ phpCAS::trace("Using CAS_ProxyChain_Any. No proxy validation is performed.");
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxyChain/Interface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * An interface for classes that define a list of allowed proxies in front of
+ * the current application.
+ *
+ * @class CAS_ProxyChain_Interface
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+interface CAS_ProxyChain_Interface
+{
+
+ /**
+ * Match a list of proxies.
+ *
+ * @param array $list The list of proxies in front of this service.
+ *
+ * @return bool
+ */
+ public function matches(array $list);
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/ProxyChain/Trusted.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * A proxy-chain definition that defines a chain up to a trusted proxy and
+ * delegates the resposibility of validating the rest of the chain to that
+ * trusted proxy.
+ *
+ * @class CAS_ProxyChain_Trusted
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxyChain_Trusted
+extends CAS_ProxyChain
+implements CAS_ProxyChain_Interface
+{
+
+ /**
+ * Validate the size of the the list as compared to our chain.
+ *
+ * @param array $list list of proxies
+ *
+ * @return bool
+ */
+ protected function isSizeValid (array $list)
+ {
+ return (sizeof($this->chain) <= sizeof($list));
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @class CAS/ProxyTicketException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ */
+
+/**
+ * An Exception for errors related to fetching or validating proxy tickets.
+ *
+ * @class CAS_ProxyTicketException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_ProxyTicketException
+extends BadMethodCallException
+implements CAS_Exception
+{
+
+ /**
+ * Constructor
+ *
+ * @param string $message Message text
+ * @param int $code Error code
+ *
+ * @return void
+ */
+ public function __construct ($message, $code = PHPCAS_SERVICE_PT_FAILURE)
+ {
+ // Warn if the code is not in our allowed list
+ $ptCodes = array(
+ PHPCAS_SERVICE_PT_FAILURE,
+ PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+ PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
+ );
+ if (!in_array($code, $ptCodes)) {
+ trigger_error(
+ 'Invalid code '.$code
+ .' passed. Must be one of PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, or PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE.'
+ );
+ }
+
+ parent::__construct($message, $code);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Request/AbstractRequest.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Provides support for performing web-requests via curl
+ *
+ * @class CAS_Request_AbstractRequest
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+abstract class CAS_Request_AbstractRequest
+implements CAS_Request_RequestInterface
+{
+
+ protected $url = null;
+ protected $cookies = array();
+ protected $headers = array();
+ protected $isPost = false;
+ protected $postBody = null;
+ protected $caCertPath = null;
+ protected $validateCN = true;
+ private $_sent = false;
+ private $_responseHeaders = array();
+ private $_responseBody = null;
+ private $_errorMessage = '';
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url Url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+
+ $this->url = $url;
+ }
+
+ /**
+ * Add a cookie to the request.
+ *
+ * @param string $name Name of entry
+ * @param string $value value of entry
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookie ($name, $value)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+
+ $this->cookies[$name] = $value;
+ }
+
+ /**
+ * Add an array of cookies to the request.
+ * The cookie array is of the form
+ * array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2')
+ *
+ * @param array $cookies cookies to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookies (array $cookies)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+
+ $this->cookies = array_merge($this->cookies, $cookies);
+ }
+
+ /**
+ * Add a header string to the request.
+ *
+ * @param string $header Header to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeader ($header)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+
+ $this->headers[] = $header;
+ }
+
+ /**
+ * Add an array of header strings to the request.
+ *
+ * @param array $headers headers to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeaders (array $headers)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+
+ $this->headers = array_merge($this->headers, $headers);
+ }
+
+ /**
+ * Make the request a POST request rather than the default GET request.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function makePost ()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+
+ $this->isPost = true;
+ }
+
+ /**
+ * Add a POST body to the request
+ *
+ * @param string $body body to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setPostBody ($body)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+ if (!$this->isPost) {
+ throw new CAS_OutOfSequenceException(
+ 'Cannot add a POST body to a GET request, use makePost() first.'
+ );
+ }
+
+ $this->postBody = $body;
+ }
+
+ /**
+ * Specify the path to an SSL CA certificate to validate the server with.
+ *
+ * @param string $caCertPath path to cert
+ * @param bool $validate_cn valdiate CN of certificate
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setSslCaCert ($caCertPath,$validate_cn=true)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+ $this->caCertPath = $caCertPath;
+ $this->validateCN = $validate_cn;
+ }
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot send again.'
+ );
+ }
+ if (is_null($this->url) || !$this->url) {
+ throw new CAS_OutOfSequenceException(
+ 'A url must be specified via setUrl() before the request can be sent.'
+ );
+ }
+ $this->_sent = true;
+ return $this->sendRequest();
+ }
+
+ /**
+ * Send the request and store the results.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ */
+ abstract protected function sendRequest ();
+
+ /**
+ * Store the response headers.
+ *
+ * @param array $headers headers to store
+ *
+ * @return void
+ */
+ protected function storeResponseHeaders (array $headers)
+ {
+ $this->_responseHeaders = array_merge($this->_responseHeaders, $headers);
+ }
+
+ /**
+ * Store a single response header to our array.
+ *
+ * @param string $header header to store
+ *
+ * @return void
+ */
+ protected function storeResponseHeader ($header)
+ {
+ $this->_responseHeaders[] = $header;
+ }
+
+ /**
+ * Store the response body.
+ *
+ * @param string $body body to store
+ *
+ * @return void
+ */
+ protected function storeResponseBody ($body)
+ {
+ $this->_responseBody = $body;
+ }
+
+ /**
+ * Add a string to our error message.
+ *
+ * @param string $message message to add
+ *
+ * @return void
+ */
+ protected function storeErrorMessage ($message)
+ {
+ $this->_errorMessage .= $message;
+ }
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has not been sent yet. Cannot '.__METHOD__
+ );
+ }
+ return $this->_responseHeaders;
+ }
+
+ /**
+ * Answer HTTP status code of the response
+ *
+ * @return int
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ * @throws CAS_Request_Exception if the response did not contain a status code
+ */
+ public function getResponseStatusCode ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has not been sent yet. Cannot '.__METHOD__
+ );
+ }
+
+ if (!preg_match(
+ '/HTTP\/[0-9.]+\s+([0-9]+)\s*(.*)/',
+ $this->_responseHeaders[0], $matches
+ )
+ ) {
+ throw new CAS_Request_Exception(
+ 'Bad response, no status code was found in the first line.'
+ );
+ }
+
+ return intval($matches[1]);
+ }
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has not been sent yet. Cannot '.__METHOD__
+ );
+ }
+
+ return $this->_responseBody;
+ }
+
+ /**
+ * Answer a message describing any errors if the request failed.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getErrorMessage ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has not been sent yet. Cannot '.__METHOD__
+ );
+ }
+ return $this->_errorMessage;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Request/AbstractRequest.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines a class library for performing multiple web requests
+ * in batches. Implementations of this interface may perform requests serially
+ * or in parallel.
+ *
+ * @class CAS_Request_CurlMultiRequest
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_Request_CurlMultiRequest
+implements CAS_Request_MultiRequestInterface
+{
+ private $_requests = array();
+ private $_sent = false;
+
+ /*********************************************************
+ * Add Requests
+ *********************************************************/
+
+ /**
+ * Add a new Request to this batch.
+ * Note, implementations will likely restrict requests to their own concrete
+ * class hierarchy.
+ *
+ * @param CAS_Request_RequestInterface $request reqest to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ * @throws CAS_InvalidArgumentException If passed a Request of the wrong
+ * implmentation.
+ */
+ public function addRequest (CAS_Request_RequestInterface $request)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+ if (!$request instanceof CAS_Request_CurlRequest) {
+ throw new CAS_InvalidArgumentException(
+ 'As a CAS_Request_CurlMultiRequest, I can only work with CAS_Request_CurlRequest objects.'
+ );
+ }
+
+ $this->_requests[] = $request;
+ }
+
+ /**
+ * Retrieve the number of requests added to this batch.
+ *
+ * @return int number of request elements
+ * @throws CAS_OutOfSequenceException if the request has already been sent
+ */
+ public function getNumRequests()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot '.__METHOD__
+ );
+ }
+ return count($this->_requests);
+ }
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request. After sending, all requests will have their
+ * responses poulated.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException(
+ 'Request has already been sent cannot send again.'
+ );
+ }
+ if (!count($this->_requests)) {
+ throw new CAS_OutOfSequenceException(
+ 'At least one request must be added via addRequest() before the multi-request can be sent.'
+ );
+ }
+
+ $this->_sent = true;
+
+ // Initialize our handles and configure all requests.
+ $handles = array();
+ $multiHandle = curl_multi_init();
+ foreach ($this->_requests as $i => $request) {
+ $handle = $request->initAndConfigure();
+ curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
+ $handles[$i] = $handle;
+ curl_multi_add_handle($multiHandle, $handle);
+ }
+
+ // Execute the requests in parallel.
+ do {
+ curl_multi_exec($multiHandle, $running);
+ } while ($running > 0);
+
+ // Populate all of the responses or errors back into the request objects.
+ foreach ($this->_requests as $i => $request) {
+ $buf = curl_multi_getcontent($handles[$i]);
+ $request->_storeResponseBody($buf);
+ curl_multi_remove_handle($multiHandle, $handles[$i]);
+ curl_close($handles[$i]);
+ }
+
+ curl_multi_close($multiHandle);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Request/CurlRequest.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Provides support for performing web-requests via curl
+ *
+ * @class CAS_Request_CurlRequest
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_Request_CurlRequest
+extends CAS_Request_AbstractRequest
+implements CAS_Request_RequestInterface
+{
+
+ /**
+ * Set additional curl options
+ *
+ * @param array $options option to set
+ *
+ * @return void
+ */
+ public function setCurlOptions (array $options)
+ {
+ $this->_curlOptions = $options;
+ }
+ private $_curlOptions = array();
+
+ /**
+ * Send the request and store the results.
+ *
+ * @return bool true on success, false on failure.
+ */
+ protected function sendRequest ()
+ {
+ phpCAS::traceBegin();
+
+ /*********************************************************
+ * initialize the CURL session
+ *********************************************************/
+ $ch = $this->initAndConfigure();
+
+ /*********************************************************
+ * Perform the query
+ *********************************************************/
+ $buf = curl_exec($ch);
+ if ( $buf === false ) {
+ phpCAS::trace('curl_exec() failed');
+ $this->storeErrorMessage(
+ 'CURL error #'.curl_errno($ch).': '.curl_error($ch)
+ );
+ $res = false;
+ } else {
+ $this->storeResponseBody($buf);
+ phpCAS::trace("Response Body: \n".$buf."\n");
+ $res = true;
+
+ }
+ // close the CURL session
+ curl_close($ch);
+
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+
+ /**
+ * Internal method to initialize our cURL handle and configure the request.
+ * This method should NOT be used outside of the CurlRequest or the
+ * CurlMultiRequest.
+ *
+ * @return resource|false The cURL handle on success, false on failure
+ */
+ public function initAndConfigure()
+ {
+ /*********************************************************
+ * initialize the CURL session
+ *********************************************************/
+ $ch = curl_init($this->url);
+
+ if (version_compare(PHP_VERSION, '5.1.3', '>=')) {
+ //only avaible in php5
+ curl_setopt_array($ch, $this->_curlOptions);
+ } else {
+ foreach ($this->_curlOptions as $key => $value) {
+ curl_setopt($ch, $key, $value);
+ }
+ }
+
+ /*********************************************************
+ * Set SSL configuration
+ *********************************************************/
+ if ($this->caCertPath) {
+ if ($this->validateCN) {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ } else {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
+ curl_setopt($ch, CURLOPT_CAINFO, $this->caCertPath);
+ phpCAS::trace('CURL: Set CURLOPT_CAINFO ' . $this->caCertPath);
+ } else {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+
+ /*********************************************************
+ * Configure curl to capture our output.
+ *********************************************************/
+ // return the CURL output into a variable
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+ // get the HTTP header with a callback
+ curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curlReadHeaders'));
+
+ /*********************************************************
+ * Add cookie headers to our request.
+ *********************************************************/
+ if (count($this->cookies)) {
+ $cookieStrings = array();
+ foreach ($this->cookies as $name => $val) {
+ $cookieStrings[] = $name.'='.$val;
+ }
+ curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookieStrings));
+ }
+
+ /*********************************************************
+ * Add any additional headers
+ *********************************************************/
+ if (count($this->headers)) {
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
+ }
+
+ /*********************************************************
+ * Flag and Body for POST requests
+ *********************************************************/
+ if ($this->isPost) {
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postBody);
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Store the response body.
+ * This method should NOT be used outside of the CurlRequest or the
+ * CurlMultiRequest.
+ *
+ * @param string $body body to stor
+ *
+ * @return void
+ */
+ private function _storeResponseBody ($body)
+ {
+ $this->storeResponseBody($body);
+ }
+
+ /**
+ * Internal method for capturing the headers from a curl request.
+ *
+ * @param resource $ch handle of curl
+ * @param string $header header
+ *
+ * @return int
+ */
+ private function _curlReadHeaders ($ch, $header)
+ {
+ $this->storeResponseHeader($header);
+ return strlen($header);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Request/Exception.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * An Exception for problems performing requests
+ *
+ * @class CAS_Request_Exception
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_Request_Exception
+extends Exception
+implements CAS_Exception
+{
+
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Request/MultiRequestInterface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines a class library for performing multiple web requests
+ * in batches. Implementations of this interface may perform requests serially
+ * or in parallel.
+ *
+ * @class CAS_Request_MultiRequestInterface
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+interface CAS_Request_MultiRequestInterface
+{
+
+ /*********************************************************
+ * Add Requests
+ *********************************************************/
+
+ /**
+ * Add a new Request to this batch.
+ * Note, implementations will likely restrict requests to their own concrete
+ * class hierarchy.
+ *
+ * @param CAS_Request_RequestInterface $request request interface
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been
+ * sent.
+ * @throws CAS_InvalidArgumentException If passed a Request of the wrong
+ * implmentation.
+ */
+ public function addRequest (CAS_Request_RequestInterface $request);
+
+ /**
+ * Retrieve the number of requests added to this batch.
+ *
+ * @return int number of request elements
+ */
+ public function getNumRequests ();
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request. After sending, all requests will have their
+ * responses poulated.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ();
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/Request/RequestInterface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines a class library for performing web requests.
+ *
+ * @class CAS_Request_RequestInterface
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+interface CAS_Request_RequestInterface
+{
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url);
+
+ /**
+ * Add a cookie to the request.
+ *
+ * @param string $name name of cookie
+ * @param string $value value of cookie
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookie ($name, $value);
+
+ /**
+ * Add an array of cookies to the request.
+ * The cookie array is of the form
+ * array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2')
+ *
+ * @param array $cookies cookies to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookies (array $cookies);
+
+ /**
+ * Add a header string to the request.
+ *
+ * @param string $header header to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeader ($header);
+
+ /**
+ * Add an array of header strings to the request.
+ *
+ * @param array $headers headers to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeaders (array $headers);
+
+ /**
+ * Make the request a POST request rather than the default GET request.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function makePost ();
+
+ /**
+ * Add a POST body to the request
+ *
+ * @param string $body body to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setPostBody ($body);
+
+
+ /**
+ * Specify the path to an SSL CA certificate to validate the server with.
+ *
+ * @param string $caCertPath path to cert file
+ * @param boolean $validate_cn validate CN of SSL certificate
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setSslCaCert ($caCertPath, $validate_cn = true);
+
+
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ();
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ();
+
+ /**
+ * Answer HTTP status code of the response
+ *
+ * @return int
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseStatusCode ();
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ();
+
+ /**
+ * Answer a message describing any errors if the request failed.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getErrorMessage ();
+}
--- /dev/null
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file CAS/InvalidArgumentException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Exception that denotes invalid arguments were passed.
+ *
+ * @class CAS_InvalidArgumentException
+ * @category Authentication
+ * @package PhpCAS
+ * @author Adam Franco <afranco@middlebury.edu>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+class CAS_TypeMismatchException
+extends CAS_InvalidArgumentException
+{
+ /**
+ * Constructor, provides a nice message.
+ *
+ * @param mixed $argument Argument
+ * @param string $argumentName Argument Name
+ * @param string $type Type
+ * @param string $message Error Message
+ * @param integer $code Code
+ *
+ * @return void
+ */
+ public function __construct (
+ $argument, $argumentName, $type, $message = '', $code = 0
+ ) {
+ if (is_object($argument)) {
+ $foundType = get_class($argument).' object';
+ } else {
+ $foundType = gettype($argument);
+ }
+
+ parent::__construct(
+ 'type mismatched for parameter '
+ . $argumentName . ' (should be \'' . $type .' \'), '
+ . $foundType . ' given. ' . $message, $code
+ );
+ }
+}
+?>
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit4f5ec3b37be240134637564819b99dd2::getLoader();
+return ComposerAutoloaderInit444c3f31864f68a3f466e2c19837e185::getLoader();
'Auth_Yadis_Yadis' => $vendorDir . '/openid/php-openid/Auth/Yadis/Yadis.php',
'Auth_Yadis_dom' => $vendorDir . '/openid/php-openid/Auth/Yadis/XML.php',
'Auth_Yadis_domxml' => $vendorDir . '/openid/php-openid/Auth/Yadis/XML.php',
+ 'CAS_AuthenticationException' => $vendorDir . '/apereo/phpcas/source/CAS/AuthenticationException.php',
+ 'CAS_Client' => $vendorDir . '/apereo/phpcas/source/CAS/Client.php',
+ 'CAS_CookieJar' => $vendorDir . '/apereo/phpcas/source/CAS/CookieJar.php',
+ 'CAS_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/Exception.php',
+ 'CAS_GracefullTerminationException' => $vendorDir . '/apereo/phpcas/source/CAS/GracefullTerminationException.php',
+ 'CAS_InvalidArgumentException' => $vendorDir . '/apereo/phpcas/source/CAS/InvalidArgumentException.php',
+ 'CAS_Languages_Catalan' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Catalan.php',
+ 'CAS_Languages_ChineseSimplified' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php',
+ 'CAS_Languages_English' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/English.php',
+ 'CAS_Languages_French' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/French.php',
+ 'CAS_Languages_German' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/German.php',
+ 'CAS_Languages_Greek' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Greek.php',
+ 'CAS_Languages_Japanese' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Japanese.php',
+ 'CAS_Languages_LanguageInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/LanguageInterface.php',
+ 'CAS_Languages_Spanish' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Spanish.php',
+ 'CAS_OutOfSequenceBeforeAuthenticationCallException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php',
+ 'CAS_OutOfSequenceBeforeClientException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php',
+ 'CAS_OutOfSequenceBeforeProxyException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php',
+ 'CAS_OutOfSequenceException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceException.php',
+ 'CAS_PGTStorage_AbstractStorage' => $vendorDir . '/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php',
+ 'CAS_PGTStorage_Db' => $vendorDir . '/apereo/phpcas/source/CAS/PGTStorage/Db.php',
+ 'CAS_PGTStorage_File' => $vendorDir . '/apereo/phpcas/source/CAS/PGTStorage/File.php',
+ 'CAS_ProxiedService' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService.php',
+ 'CAS_ProxiedService_Abstract' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Abstract.php',
+ 'CAS_ProxiedService_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Exception.php',
+ 'CAS_ProxiedService_Http' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http.php',
+ 'CAS_ProxiedService_Http_Abstract' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php',
+ 'CAS_ProxiedService_Http_Get' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php',
+ 'CAS_ProxiedService_Http_Post' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php',
+ 'CAS_ProxiedService_Imap' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Imap.php',
+ 'CAS_ProxiedService_Testable' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Testable.php',
+ 'CAS_ProxyChain' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain.php',
+ 'CAS_ProxyChain_AllowedList' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php',
+ 'CAS_ProxyChain_Any' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/Any.php',
+ 'CAS_ProxyChain_Interface' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/Interface.php',
+ 'CAS_ProxyChain_Trusted' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/Trusted.php',
+ 'CAS_ProxyTicketException' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyTicketException.php',
+ 'CAS_Request_AbstractRequest' => $vendorDir . '/apereo/phpcas/source/CAS/Request/AbstractRequest.php',
+ 'CAS_Request_CurlMultiRequest' => $vendorDir . '/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php',
+ 'CAS_Request_CurlRequest' => $vendorDir . '/apereo/phpcas/source/CAS/Request/CurlRequest.php',
+ 'CAS_Request_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/Request/Exception.php',
+ 'CAS_Request_MultiRequestInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php',
+ 'CAS_Request_RequestInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Request/RequestInterface.php',
+ 'CAS_TypeMismatchException' => $vendorDir . '/apereo/phpcas/source/CAS/TypeMismatchException.php',
'HTMLPurifier' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.php',
'HTMLPurifier_Arborize' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php',
'HTMLPurifier_AttrCollections' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php',
'Masterminds\\HTML5\\Serializer\\OutputRules' => $vendorDir . '/masterminds/html5/src/HTML5/Serializer/OutputRules.php',
'Masterminds\\HTML5\\Serializer\\RulesInterface' => $vendorDir . '/masterminds/html5/src/HTML5/Serializer/RulesInterface.php',
'Masterminds\\HTML5\\Serializer\\Traverser' => $vendorDir . '/masterminds/html5/src/HTML5/Serializer/Traverser.php',
+ 'Michelf\\Markdown' => $vendorDir . '/michelf/php-markdown/Michelf/Markdown.php',
+ 'Michelf\\MarkdownExtra' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownExtra.php',
+ 'Michelf\\MarkdownInterface' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownInterface.php',
+ 'ParagonIE\\ConstantTime\\Base32' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32.php',
+ 'ParagonIE\\ConstantTime\\Base32Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32Hex.php',
+ 'ParagonIE\\ConstantTime\\Base64' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlash' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlash.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
+ 'ParagonIE\\ConstantTime\\Base64UrlSafe' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php',
+ 'ParagonIE\\ConstantTime\\Binary' => $vendorDir . '/paragonie/constant_time_encoding/src/Binary.php',
+ 'ParagonIE\\ConstantTime\\EncoderInterface' => $vendorDir . '/paragonie/constant_time_encoding/src/EncoderInterface.php',
+ 'ParagonIE\\ConstantTime\\Encoding' => $vendorDir . '/paragonie/constant_time_encoding/src/Encoding.php',
+ 'ParagonIE\\ConstantTime\\Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Hex.php',
+ 'ParagonIE\\ConstantTime\\RFC4648' => $vendorDir . '/paragonie/constant_time_encoding/src/RFC4648.php',
+ 'Stomp\\Broker\\ActiveMq\\ActiveMq' => $vendorDir . '/stomp-php/stomp-php/src/Broker/ActiveMq/ActiveMq.php',
+ 'Stomp\\Broker\\ActiveMq\\Mode\\ActiveMqMode' => $vendorDir . '/stomp-php/stomp-php/src/Broker/ActiveMq/Mode/ActiveMqMode.php',
+ 'Stomp\\Broker\\ActiveMq\\Mode\\DurableSubscription' => $vendorDir . '/stomp-php/stomp-php/src/Broker/ActiveMq/Mode/DurableSubscription.php',
+ 'Stomp\\Broker\\ActiveMq\\Options' => $vendorDir . '/stomp-php/stomp-php/src/Broker/ActiveMq/Options.php',
+ 'Stomp\\Broker\\Apollo\\Apollo' => $vendorDir . '/stomp-php/stomp-php/src/Broker/Apollo/Apollo.php',
+ 'Stomp\\Broker\\Apollo\\Mode\\QueueBrowser' => $vendorDir . '/stomp-php/stomp-php/src/Broker/Apollo/Mode/QueueBrowser.php',
+ 'Stomp\\Broker\\Apollo\\Mode\\SequenceQueueBrowser' => $vendorDir . '/stomp-php/stomp-php/src/Broker/Apollo/Mode/SequenceQueueBrowser.php',
+ 'Stomp\\Broker\\Exception\\UnsupportedBrokerException' => $vendorDir . '/stomp-php/stomp-php/src/Broker/Exception/UnsupportedBrokerException.php',
+ 'Stomp\\Broker\\OpenMq\\OpenMq' => $vendorDir . '/stomp-php/stomp-php/src/Broker/OpenMq/OpenMq.php',
+ 'Stomp\\Broker\\RabbitMq\\RabbitMq' => $vendorDir . '/stomp-php/stomp-php/src/Broker/RabbitMq/RabbitMq.php',
+ 'Stomp\\Client' => $vendorDir . '/stomp-php/stomp-php/src/Client.php',
+ 'Stomp\\Exception\\ConnectionException' => $vendorDir . '/stomp-php/stomp-php/src/Exception/ConnectionException.php',
+ 'Stomp\\Exception\\ErrorFrameException' => $vendorDir . '/stomp-php/stomp-php/src/Exception/ErrorFrameException.php',
+ 'Stomp\\Exception\\MissingReceiptException' => $vendorDir . '/stomp-php/stomp-php/src/Exception/MissingReceiptException.php',
+ 'Stomp\\Exception\\StompException' => $vendorDir . '/stomp-php/stomp-php/src/Exception/StompException.php',
+ 'Stomp\\Exception\\UnexpectedResponseException' => $vendorDir . '/stomp-php/stomp-php/src/Exception/UnexpectedResponseException.php',
+ 'Stomp\\Network\\Connection' => $vendorDir . '/stomp-php/stomp-php/src/Network/Connection.php',
+ 'Stomp\\Network\\Observer\\AbstractBeats' => $vendorDir . '/stomp-php/stomp-php/src/Network/Observer/AbstractBeats.php',
+ 'Stomp\\Network\\Observer\\ConnectionObserver' => $vendorDir . '/stomp-php/stomp-php/src/Network/Observer/ConnectionObserver.php',
+ 'Stomp\\Network\\Observer\\ConnectionObserverCollection' => $vendorDir . '/stomp-php/stomp-php/src/Network/Observer/ConnectionObserverCollection.php',
+ 'Stomp\\Network\\Observer\\Exception\\HeartbeatException' => $vendorDir . '/stomp-php/stomp-php/src/Network/Observer/Exception/HeartbeatException.php',
+ 'Stomp\\Network\\Observer\\HeartbeatEmitter' => $vendorDir . '/stomp-php/stomp-php/src/Network/Observer/HeartbeatEmitter.php',
+ 'Stomp\\Network\\Observer\\ServerAliveObserver' => $vendorDir . '/stomp-php/stomp-php/src/Network/Observer/ServerAliveObserver.php',
+ 'Stomp\\Protocol\\Protocol' => $vendorDir . '/stomp-php/stomp-php/src/Protocol/Protocol.php',
+ 'Stomp\\Protocol\\Version' => $vendorDir . '/stomp-php/stomp-php/src/Protocol/Version.php',
+ 'Stomp\\SimpleStomp' => $vendorDir . '/stomp-php/stomp-php/src/SimpleStomp.php',
+ 'Stomp\\StatefulStomp' => $vendorDir . '/stomp-php/stomp-php/src/StatefulStomp.php',
+ 'Stomp\\States\\ConsumerState' => $vendorDir . '/stomp-php/stomp-php/src/States/ConsumerState.php',
+ 'Stomp\\States\\ConsumerTransactionState' => $vendorDir . '/stomp-php/stomp-php/src/States/ConsumerTransactionState.php',
+ 'Stomp\\States\\Exception\\InvalidStateException' => $vendorDir . '/stomp-php/stomp-php/src/States/Exception/InvalidStateException.php',
+ 'Stomp\\States\\IStateful' => $vendorDir . '/stomp-php/stomp-php/src/States/IStateful.php',
+ 'Stomp\\States\\Meta\\Subscription' => $vendorDir . '/stomp-php/stomp-php/src/States/Meta/Subscription.php',
+ 'Stomp\\States\\Meta\\SubscriptionList' => $vendorDir . '/stomp-php/stomp-php/src/States/Meta/SubscriptionList.php',
+ 'Stomp\\States\\ProducerState' => $vendorDir . '/stomp-php/stomp-php/src/States/ProducerState.php',
+ 'Stomp\\States\\ProducerTransactionState' => $vendorDir . '/stomp-php/stomp-php/src/States/ProducerTransactionState.php',
+ 'Stomp\\States\\StateSetter' => $vendorDir . '/stomp-php/stomp-php/src/States/StateSetter.php',
+ 'Stomp\\States\\StateTemplate' => $vendorDir . '/stomp-php/stomp-php/src/States/StateTemplate.php',
+ 'Stomp\\States\\TransactionsTrait' => $vendorDir . '/stomp-php/stomp-php/src/States/TransactionsTrait.php',
+ 'Stomp\\Transport\\Bytes' => $vendorDir . '/stomp-php/stomp-php/src/Transport/Bytes.php',
+ 'Stomp\\Transport\\Frame' => $vendorDir . '/stomp-php/stomp-php/src/Transport/Frame.php',
+ 'Stomp\\Transport\\FrameFactory' => $vendorDir . '/stomp-php/stomp-php/src/Transport/FrameFactory.php',
+ 'Stomp\\Transport\\Map' => $vendorDir . '/stomp-php/stomp-php/src/Transport/Map.php',
+ 'Stomp\\Transport\\Message' => $vendorDir . '/stomp-php/stomp-php/src/Transport/Message.php',
+ 'Stomp\\Transport\\Parser' => $vendorDir . '/stomp-php/stomp-php/src/Transport/Parser.php',
+ 'Stomp\\Util\\IdGenerator' => $vendorDir . '/stomp-php/stomp-php/src/Util/IdGenerator.php',
+ 'XMPPHP\\BOSH' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/BOSH.php',
+ 'XMPPHP\\Exception' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/Exception.php',
+ 'XMPPHP\\Log' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/Log.php',
+ 'XMPPHP\\Roster' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/Roster.php',
+ 'XMPPHP\\XMLObj' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/XMLObj.php',
+ 'XMPPHP\\XMLStream' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/XMLStream.php',
+ 'XMPPHP\\XMPP' => $vendorDir . '/diogocomposer/xmpphp/XMPPHP/XMPP.php',
+ 'phpCAS' => $vendorDir . '/apereo/phpcas/source/CAS.php',
+ 'phpseclib\\Crypt\\AES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
+ 'phpseclib\\Crypt\\Base' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
+ 'phpseclib\\Crypt\\Blowfish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
+ 'phpseclib\\Crypt\\DES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
+ 'phpseclib\\Crypt\\Hash' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
+ 'phpseclib\\Crypt\\RC2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
+ 'phpseclib\\Crypt\\RC4' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
+ 'phpseclib\\Crypt\\RSA' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
+ 'phpseclib\\Crypt\\Random' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
+ 'phpseclib\\Crypt\\Rijndael' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
+ 'phpseclib\\Crypt\\TripleDES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
+ 'phpseclib\\Crypt\\Twofish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
+ 'phpseclib\\File\\ANSI' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ANSI.php',
+ 'phpseclib\\File\\ASN1' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ASN1.php',
+ 'phpseclib\\File\\ASN1\\Element' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
+ 'phpseclib\\File\\X509' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/X509.php',
+ 'phpseclib\\Math\\BigInteger' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
+ 'phpseclib\\Net\\SCP' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SCP.php',
+ 'phpseclib\\Net\\SFTP' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SFTP.php',
+ 'phpseclib\\Net\\SFTP\\Stream' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php',
+ 'phpseclib\\Net\\SSH1' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SSH1.php',
+ 'phpseclib\\Net\\SSH2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SSH2.php',
+ 'phpseclib\\System\\SSH\\Agent' => $vendorDir . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php',
+ 'phpseclib\\System\\SSH\\Agent\\Identity' => $vendorDir . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php',
);
return array(
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'757772e28a0943a9afe83def8db95bdf' => $vendorDir . '/mf2/mf2/Mf2/Parser.php',
+ 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
);
$baseDir = dirname($vendorDir);
return array(
+ 'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
+ 'XMPPHP\\' => array($vendorDir . '/diogocomposer/xmpphp/XMPPHP'),
+ 'Stomp\\' => array($vendorDir . '/stomp-php/stomp-php/src'),
+ 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
+ 'Michelf\\' => array($vendorDir . '/michelf/php-markdown/Michelf'),
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
);
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit4f5ec3b37be240134637564819b99dd2
+class ComposerAutoloaderInit444c3f31864f68a3f466e2c19837e185
{
private static $loader;
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInit4f5ec3b37be240134637564819b99dd2', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit444c3f31864f68a3f466e2c19837e185', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInit4f5ec3b37be240134637564819b99dd2', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit444c3f31864f68a3f466e2c19837e185', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';
$includePaths[] = get_include_path();
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
- call_user_func(\Composer\Autoload\ComposerStaticInit4f5ec3b37be240134637564819b99dd2::getInitializer($loader));
+ call_user_func(\Composer\Autoload\ComposerStaticInit444c3f31864f68a3f466e2c19837e185::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->register(true);
if ($useStaticLoader) {
- $includeFiles = Composer\Autoload\ComposerStaticInit4f5ec3b37be240134637564819b99dd2::$files;
+ $includeFiles = Composer\Autoload\ComposerStaticInit444c3f31864f68a3f466e2c19837e185::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
- composerRequire4f5ec3b37be240134637564819b99dd2($fileIdentifier, $file);
+ composerRequire444c3f31864f68a3f466e2c19837e185($fileIdentifier, $file);
}
return $loader;
}
}
-function composerRequire4f5ec3b37be240134637564819b99dd2($fileIdentifier, $file)
+function composerRequire444c3f31864f68a3f466e2c19837e185($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
namespace Composer\Autoload;
-class ComposerStaticInit4f5ec3b37be240134637564819b99dd2
+class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
{
public static $files = array (
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'757772e28a0943a9afe83def8db95bdf' => __DIR__ . '/..' . '/mf2/mf2/Mf2/Parser.php',
+ 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
);
public static $prefixLengthsPsr4 = array (
+ 'p' =>
+ array (
+ 'phpseclib\\' => 10,
+ ),
+ 'X' =>
+ array (
+ 'XMPPHP\\' => 7,
+ ),
+ 'S' =>
+ array (
+ 'Stomp\\' => 6,
+ ),
+ 'P' =>
+ array (
+ 'ParagonIE\\ConstantTime\\' => 23,
+ ),
'M' =>
array (
+ 'Michelf\\' => 8,
'Masterminds\\' => 12,
),
);
public static $prefixDirsPsr4 = array (
+ 'phpseclib\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
+ ),
+ 'XMPPHP\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP',
+ ),
+ 'Stomp\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/stomp-php/stomp-php/src',
+ ),
+ 'ParagonIE\\ConstantTime\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
+ ),
+ 'Michelf\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/michelf/php-markdown/Michelf',
+ ),
'Masterminds\\' =>
array (
0 => __DIR__ . '/..' . '/masterminds/html5/src',
'Auth_Yadis_Yadis' => __DIR__ . '/..' . '/openid/php-openid/Auth/Yadis/Yadis.php',
'Auth_Yadis_dom' => __DIR__ . '/..' . '/openid/php-openid/Auth/Yadis/XML.php',
'Auth_Yadis_domxml' => __DIR__ . '/..' . '/openid/php-openid/Auth/Yadis/XML.php',
+ 'CAS_AuthenticationException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/AuthenticationException.php',
+ 'CAS_Client' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Client.php',
+ 'CAS_CookieJar' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/CookieJar.php',
+ 'CAS_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Exception.php',
+ 'CAS_GracefullTerminationException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/GracefullTerminationException.php',
+ 'CAS_InvalidArgumentException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/InvalidArgumentException.php',
+ 'CAS_Languages_Catalan' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Catalan.php',
+ 'CAS_Languages_ChineseSimplified' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php',
+ 'CAS_Languages_English' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/English.php',
+ 'CAS_Languages_French' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/French.php',
+ 'CAS_Languages_German' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/German.php',
+ 'CAS_Languages_Greek' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Greek.php',
+ 'CAS_Languages_Japanese' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Japanese.php',
+ 'CAS_Languages_LanguageInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/LanguageInterface.php',
+ 'CAS_Languages_Spanish' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Spanish.php',
+ 'CAS_OutOfSequenceBeforeAuthenticationCallException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php',
+ 'CAS_OutOfSequenceBeforeClientException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php',
+ 'CAS_OutOfSequenceBeforeProxyException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php',
+ 'CAS_OutOfSequenceException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceException.php',
+ 'CAS_PGTStorage_AbstractStorage' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php',
+ 'CAS_PGTStorage_Db' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/PGTStorage/Db.php',
+ 'CAS_PGTStorage_File' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/PGTStorage/File.php',
+ 'CAS_ProxiedService' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService.php',
+ 'CAS_ProxiedService_Abstract' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Abstract.php',
+ 'CAS_ProxiedService_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Exception.php',
+ 'CAS_ProxiedService_Http' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http.php',
+ 'CAS_ProxiedService_Http_Abstract' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php',
+ 'CAS_ProxiedService_Http_Get' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php',
+ 'CAS_ProxiedService_Http_Post' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php',
+ 'CAS_ProxiedService_Imap' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Imap.php',
+ 'CAS_ProxiedService_Testable' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Testable.php',
+ 'CAS_ProxyChain' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain.php',
+ 'CAS_ProxyChain_AllowedList' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php',
+ 'CAS_ProxyChain_Any' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/Any.php',
+ 'CAS_ProxyChain_Interface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/Interface.php',
+ 'CAS_ProxyChain_Trusted' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/Trusted.php',
+ 'CAS_ProxyTicketException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyTicketException.php',
+ 'CAS_Request_AbstractRequest' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/AbstractRequest.php',
+ 'CAS_Request_CurlMultiRequest' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php',
+ 'CAS_Request_CurlRequest' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/CurlRequest.php',
+ 'CAS_Request_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/Exception.php',
+ 'CAS_Request_MultiRequestInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php',
+ 'CAS_Request_RequestInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/RequestInterface.php',
+ 'CAS_TypeMismatchException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/TypeMismatchException.php',
'HTMLPurifier' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.php',
'HTMLPurifier_Arborize' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php',
'HTMLPurifier_AttrCollections' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php',
'Masterminds\\HTML5\\Serializer\\OutputRules' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Serializer/OutputRules.php',
'Masterminds\\HTML5\\Serializer\\RulesInterface' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Serializer/RulesInterface.php',
'Masterminds\\HTML5\\Serializer\\Traverser' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Serializer/Traverser.php',
+ 'Michelf\\Markdown' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/Markdown.php',
+ 'Michelf\\MarkdownExtra' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownExtra.php',
+ 'Michelf\\MarkdownInterface' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownInterface.php',
+ 'ParagonIE\\ConstantTime\\Base32' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32.php',
+ 'ParagonIE\\ConstantTime\\Base32Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32Hex.php',
+ 'ParagonIE\\ConstantTime\\Base64' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlash' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlash.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
+ 'ParagonIE\\ConstantTime\\Base64UrlSafe' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php',
+ 'ParagonIE\\ConstantTime\\Binary' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Binary.php',
+ 'ParagonIE\\ConstantTime\\EncoderInterface' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/EncoderInterface.php',
+ 'ParagonIE\\ConstantTime\\Encoding' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Encoding.php',
+ 'ParagonIE\\ConstantTime\\Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Hex.php',
+ 'ParagonIE\\ConstantTime\\RFC4648' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/RFC4648.php',
+ 'Stomp\\Broker\\ActiveMq\\ActiveMq' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/ActiveMq/ActiveMq.php',
+ 'Stomp\\Broker\\ActiveMq\\Mode\\ActiveMqMode' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/ActiveMq/Mode/ActiveMqMode.php',
+ 'Stomp\\Broker\\ActiveMq\\Mode\\DurableSubscription' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/ActiveMq/Mode/DurableSubscription.php',
+ 'Stomp\\Broker\\ActiveMq\\Options' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/ActiveMq/Options.php',
+ 'Stomp\\Broker\\Apollo\\Apollo' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/Apollo/Apollo.php',
+ 'Stomp\\Broker\\Apollo\\Mode\\QueueBrowser' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/Apollo/Mode/QueueBrowser.php',
+ 'Stomp\\Broker\\Apollo\\Mode\\SequenceQueueBrowser' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/Apollo/Mode/SequenceQueueBrowser.php',
+ 'Stomp\\Broker\\Exception\\UnsupportedBrokerException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/Exception/UnsupportedBrokerException.php',
+ 'Stomp\\Broker\\OpenMq\\OpenMq' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/OpenMq/OpenMq.php',
+ 'Stomp\\Broker\\RabbitMq\\RabbitMq' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Broker/RabbitMq/RabbitMq.php',
+ 'Stomp\\Client' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Client.php',
+ 'Stomp\\Exception\\ConnectionException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Exception/ConnectionException.php',
+ 'Stomp\\Exception\\ErrorFrameException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Exception/ErrorFrameException.php',
+ 'Stomp\\Exception\\MissingReceiptException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Exception/MissingReceiptException.php',
+ 'Stomp\\Exception\\StompException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Exception/StompException.php',
+ 'Stomp\\Exception\\UnexpectedResponseException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Exception/UnexpectedResponseException.php',
+ 'Stomp\\Network\\Connection' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Connection.php',
+ 'Stomp\\Network\\Observer\\AbstractBeats' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Observer/AbstractBeats.php',
+ 'Stomp\\Network\\Observer\\ConnectionObserver' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Observer/ConnectionObserver.php',
+ 'Stomp\\Network\\Observer\\ConnectionObserverCollection' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Observer/ConnectionObserverCollection.php',
+ 'Stomp\\Network\\Observer\\Exception\\HeartbeatException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Observer/Exception/HeartbeatException.php',
+ 'Stomp\\Network\\Observer\\HeartbeatEmitter' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Observer/HeartbeatEmitter.php',
+ 'Stomp\\Network\\Observer\\ServerAliveObserver' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Network/Observer/ServerAliveObserver.php',
+ 'Stomp\\Protocol\\Protocol' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Protocol/Protocol.php',
+ 'Stomp\\Protocol\\Version' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Protocol/Version.php',
+ 'Stomp\\SimpleStomp' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/SimpleStomp.php',
+ 'Stomp\\StatefulStomp' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/StatefulStomp.php',
+ 'Stomp\\States\\ConsumerState' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/ConsumerState.php',
+ 'Stomp\\States\\ConsumerTransactionState' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/ConsumerTransactionState.php',
+ 'Stomp\\States\\Exception\\InvalidStateException' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/Exception/InvalidStateException.php',
+ 'Stomp\\States\\IStateful' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/IStateful.php',
+ 'Stomp\\States\\Meta\\Subscription' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/Meta/Subscription.php',
+ 'Stomp\\States\\Meta\\SubscriptionList' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/Meta/SubscriptionList.php',
+ 'Stomp\\States\\ProducerState' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/ProducerState.php',
+ 'Stomp\\States\\ProducerTransactionState' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/ProducerTransactionState.php',
+ 'Stomp\\States\\StateSetter' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/StateSetter.php',
+ 'Stomp\\States\\StateTemplate' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/StateTemplate.php',
+ 'Stomp\\States\\TransactionsTrait' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/States/TransactionsTrait.php',
+ 'Stomp\\Transport\\Bytes' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Transport/Bytes.php',
+ 'Stomp\\Transport\\Frame' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Transport/Frame.php',
+ 'Stomp\\Transport\\FrameFactory' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Transport/FrameFactory.php',
+ 'Stomp\\Transport\\Map' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Transport/Map.php',
+ 'Stomp\\Transport\\Message' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Transport/Message.php',
+ 'Stomp\\Transport\\Parser' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Transport/Parser.php',
+ 'Stomp\\Util\\IdGenerator' => __DIR__ . '/..' . '/stomp-php/stomp-php/src/Util/IdGenerator.php',
+ 'XMPPHP\\BOSH' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/BOSH.php',
+ 'XMPPHP\\Exception' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/Exception.php',
+ 'XMPPHP\\Log' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/Log.php',
+ 'XMPPHP\\Roster' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/Roster.php',
+ 'XMPPHP\\XMLObj' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/XMLObj.php',
+ 'XMPPHP\\XMLStream' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/XMLStream.php',
+ 'XMPPHP\\XMPP' => __DIR__ . '/..' . '/diogocomposer/xmpphp/XMPPHP/XMPP.php',
+ 'phpCAS' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS.php',
+ 'phpseclib\\Crypt\\AES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
+ 'phpseclib\\Crypt\\Base' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
+ 'phpseclib\\Crypt\\Blowfish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
+ 'phpseclib\\Crypt\\DES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
+ 'phpseclib\\Crypt\\Hash' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
+ 'phpseclib\\Crypt\\RC2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
+ 'phpseclib\\Crypt\\RC4' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
+ 'phpseclib\\Crypt\\RSA' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
+ 'phpseclib\\Crypt\\Random' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
+ 'phpseclib\\Crypt\\Rijndael' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
+ 'phpseclib\\Crypt\\TripleDES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
+ 'phpseclib\\Crypt\\Twofish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
+ 'phpseclib\\File\\ANSI' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ANSI.php',
+ 'phpseclib\\File\\ASN1' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ASN1.php',
+ 'phpseclib\\File\\ASN1\\Element' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
+ 'phpseclib\\File\\X509' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/X509.php',
+ 'phpseclib\\Math\\BigInteger' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
+ 'phpseclib\\Net\\SCP' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SCP.php',
+ 'phpseclib\\Net\\SFTP' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SFTP.php',
+ 'phpseclib\\Net\\SFTP\\Stream' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php',
+ 'phpseclib\\Net\\SSH1' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SSH1.php',
+ 'phpseclib\\Net\\SSH2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SSH2.php',
+ 'phpseclib\\System\\SSH\\Agent' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php',
+ 'phpseclib\\System\\SSH\\Agent\\Identity' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit4f5ec3b37be240134637564819b99dd2::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit4f5ec3b37be240134637564819b99dd2::$prefixDirsPsr4;
- $loader->prefixesPsr0 = ComposerStaticInit4f5ec3b37be240134637564819b99dd2::$prefixesPsr0;
- $loader->classMap = ComposerStaticInit4f5ec3b37be240134637564819b99dd2::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit444c3f31864f68a3f466e2c19837e185::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit444c3f31864f68a3f466e2c19837e185::$prefixDirsPsr4;
+ $loader->prefixesPsr0 = ComposerStaticInit444c3f31864f68a3f466e2c19837e185::$prefixesPsr0;
+ $loader->classMap = ComposerStaticInit444c3f31864f68a3f466e2c19837e185::$classMap;
}, null, ClassLoader::class);
}
[
+ {
+ "name": "apereo/phpcas",
+ "version": "1.3.7",
+ "version_normalized": "1.3.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/apereo/phpCAS.git",
+ "reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/apereo/phpCAS/zipball/b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
+ "reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~3.7.10"
+ },
+ "time": "2019-04-22T19:48:16+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "source/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Joachim Fritschi",
+ "homepage": "https://wiki.jasig.org/display/~fritschi"
+ },
+ {
+ "name": "Adam Franco",
+ "homepage": "https://wiki.jasig.org/display/~adamfranco"
+ }
+ ],
+ "description": "Provides a simple API for authenticating users against a CAS server",
+ "homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
+ "keywords": [
+ "apereo",
+ "cas",
+ "jasig"
+ ]
+ },
+ {
+ "name": "diogocomposer/xmpphp",
+ "version": "v3.0.0",
+ "version_normalized": "3.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/diogogithub/xmpphp.git",
+ "reference": "c7cdcc588aa47893ab41a1670c5dfe649674a4b0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/diogogithub/xmpphp/zipball/c7cdcc588aa47893ab41a1670c5dfe649674a4b0",
+ "reference": "c7cdcc588aa47893ab41a1670c5dfe649674a4b0",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "php": ">=7.0.0"
+ },
+ "time": "2019-06-19T02:32:32+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "XMPPHP\\": "XMPPHP"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Ivan Borzenkov",
+ "email": "ivan.borzenkov@gmail.com"
+ },
+ {
+ "name": "bandroidx",
+ "email": "bandroidx@gmail.com"
+ },
+ {
+ "name": "BirknerAlex",
+ "email": "alex.birkner@gmail.com"
+ },
+ {
+ "name": "Stephan Wentz",
+ "email": "stephan@wentz.it"
+ },
+ {
+ "name": "Nathan Fritz",
+ "email": "fritzy@netflint.net"
+ },
+ {
+ "name": "Christian Weiske",
+ "email": "cweiske@cweiske.de"
+ },
+ {
+ "name": "Vito Tafuni",
+ "email": "vitotafuni@gmail.com"
+ },
+ {
+ "name": "Diogo Cordeiro",
+ "email": "diogo@fc.up.pt"
+ }
+ ],
+ "description": "XMPP PHP Library",
+ "keywords": [
+ "jabber",
+ "xmpp",
+ "xmpphp"
+ ]
+ },
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
"semantic"
]
},
+ {
+ "name": "michelf/php-markdown",
+ "version": "1.8.0",
+ "version_normalized": "1.8.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/michelf/php-markdown.git",
+ "reference": "01ab082b355bf188d907b9929cd99b2923053495"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495",
+ "reference": "01ab082b355bf188d907b9929cd99b2923053495",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2018-01-15T00:49:33+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Michelf\\": "Michelf/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Michel Fortin",
+ "email": "michel.fortin@michelf.ca",
+ "homepage": "https://michelf.ca/",
+ "role": "Developer"
+ },
+ {
+ "name": "John Gruber",
+ "homepage": "https://daringfireball.net/"
+ }
+ ],
+ "description": "PHP Markdown",
+ "homepage": "https://michelf.ca/projects/php-markdown/",
+ "keywords": [
+ "markdown"
+ ]
+ },
{
"name": "openid/php-openid",
"version": "2.3.0",
"auth",
"yadis"
]
+ },
+ {
+ "name": "paragonie/constant_time_encoding",
+ "version": "v1.0.4",
+ "version_normalized": "1.0.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
+ "reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
+ "reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3|^7"
+ },
+ "require-dev": {
+ "paragonie/random_compat": "^1.4|^2",
+ "phpunit/phpunit": "4.*|5.*",
+ "vimeo/psalm": "^0.3|^1"
+ },
+ "time": "2018-04-30T17:57:16+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base16",
+ "base32",
+ "base32_decode",
+ "base32_encode",
+ "base64",
+ "base64_decode",
+ "base64_encode",
+ "bin2hex",
+ "encoding",
+ "hex",
+ "hex2bin",
+ "rfc4648"
+ ]
+ },
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "2.0.19",
+ "version_normalized": "2.0.19.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "d2085db7b7394baa071a69c8f9159723c250f2ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d2085db7b7394baa071a69c8f9159723c250f2ba",
+ "reference": "d2085db7b7394baa071a69c8f9159723c250f2ba",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phing/phing": "~2.7",
+ "phpunit/phpunit": "^4.8.35|^5.7|^6.0",
+ "sami/sami": "~2.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "suggest": {
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ },
+ "time": "2019-06-20T03:34:11+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "homepage": "http://phpseclib.sourceforge.net",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ]
+ },
+ {
+ "name": "stomp-php/stomp-php",
+ "version": "4.5.1",
+ "version_normalized": "4.5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/stomp-php/stomp-php.git",
+ "reference": "4c5f0a95330085a86fd852b8ad0b1fbb4e8a4158"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/stomp-php/stomp-php/zipball/4c5f0a95330085a86fd852b8ad0b1fbb4e8a4158",
+ "reference": "4c5f0a95330085a86fd852b8ad0b1fbb4e8a4158",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7"
+ },
+ "time": "2019-04-09T08:25:54+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Stomp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Dejan Bosnanac",
+ "email": "dejan@nighttale.net",
+ "homepage": "http://www.nighttale.net"
+ },
+ {
+ "name": "Sören Rohweder",
+ "email": "s.rohweder@blage.net",
+ "homepage": "http://www.monofone.de"
+ },
+ {
+ "name": "Jens Radtke",
+ "email": "swefl@fin-sn.de",
+ "homepage": "http://www.fin-sn.de"
+ }
+ ],
+ "description": "stomp support for PHP",
+ "homepage": "http://github.com/stomp-php/stomp-php",
+ "keywords": [
+ "activeMQ",
+ "apollomq",
+ "jms",
+ "messaging",
+ "rabbitmq",
+ "stomp"
+ ]
}
]
--- /dev/null
+composer.phar
+/vendor/
+
+# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
+# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
+# composer.lock
--- /dev/null
+XMPPHP: The PHP XMPP Library
+Copyright (C) 2008 Nathanael C. Fritz
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, 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 Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ 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.)
+\f
+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.
+\f
+ 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.
+\f
+ 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
+\f
+ 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 St, 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 Library General
+Public License instead of this License.
+
+Exceptions:
+
+As a special exception to this license, the "Enhanced Jabber Integration"
+project, which is a plugin for vBulletin, may use and distribute XMPPHP
+without extending the GPL license to the parent package.
+
+If you would like an exception for your free software, please contact the
+copyright holder.
--- /dev/null
+README
+======
+
+About XMPPHP
+------------
+
+XMPPHP is an elegant PHP library for XMPP (aka Jabber, Google Talk, etc).
+
+* Homepage: [http://code.google.com/p/xmpphp]
+* Chatroom: [xmpphp@conference.psi-im.org] (XMPP MUC)
+* Author: Nathan Fritz, jabber id: fritzy [at] netflint.net
+* Co-Author: Stephan Wentz, jabber id: stephan [at] wentz.it
+* This fork: https://github.com/diogogithub/xmpphp
+* Maintainer of this fork: Diogo Cordeiro <diogo@fc.up.pt>
+
+Requirements
+------------
+
+* PHP 7.0
+* SSL Support Compiled
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+use SimpleXMLElement;
+
+/** XMPPHP_XMLStream */
+require_once __DIR__ . "/XMPP.php";
+
+/**
+ * XMPPHP BOSH
+ *
+ * @property int lat
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class BOSH extends XMPP
+{
+ /**
+ * @var integer
+ */
+ protected $rid;
+
+ /**
+ * @var string
+ */
+ protected $sid;
+
+ /**
+ * @var string
+ */
+ protected $http_server;
+
+ /**
+ * @var array
+ */
+ protected $http_buffer = array();
+
+ /**
+ * @var string
+ */
+ protected $session = false;
+
+ /**
+ * @var integer
+ */
+ protected $inactivity;
+
+ /**
+ * Connect
+ *
+ * @param $server
+ * @param $wait
+ * @param $session
+ * @throws Exception
+ * @throws Exception
+ */
+ public function connect($server = null, $wait = '1', $session = false)
+ {
+
+ if (is_null($server)) {
+
+ // If we aren't given the server http url, try and guess it
+ $port_string = ($this->port AND $this->port != 80) ? ':' . $this->port : '';
+ $this->http_server = 'http://' . $this->host . $port_string . '/http-bind/';
+ } else {
+ $this->http_server = $server;
+ }
+
+ $this->use_encryption = false;
+ $this->session = $session;
+ $this->rid = 3001;
+ $this->sid = null;
+ $this->inactivity = 0;
+
+ if ($session) {
+ $this->loadSession();
+ }
+
+ if (!$this->sid) {
+
+ $body = $this->__buildBody();
+ $body->addAttribute('hold', '1');
+ $body->addAttribute('to', $this->server);
+ $body->addAttribute('route', 'xmpp:' . $this->host . ':' . $this->port);
+ $body->addAttribute('secure', 'true');
+ $body->addAttribute('xmpp:version', '1.0', 'urn:xmpp:xbosh');
+ $body->addAttribute('wait', strval($wait));
+ $body->addAttribute('ack', '1');
+ $body->addAttribute('xmlns:xmpp', 'urn:xmpp:xbosh');
+ $buff = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">';
+ xml_parse($this->parser, $buff, false);
+ $response = $this->__sendBody($body);
+ $rxml = new SimpleXMLElement($response);
+ $this->sid = $rxml['sid'];
+ $this->inactivity = $rxml['inactivity'];
+ } else {
+ $buff = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">';
+ xml_parse($this->parser, $buff, false);
+ }
+ }
+
+ /**
+ * Load session
+ *
+ */
+ public function loadSession()
+ {
+
+ if ($this->session == 'ON_FILE') {
+
+ // Session not started so use session_file
+ $session_file = $this->getSessionFile();
+
+ // manage multiple accesses
+ if (!file_exists($session_file)) {
+ file_put_contents($session_file, '');
+ }
+ $session_file_fp = fopen($session_file, 'r');
+ flock($session_file_fp, LOCK_EX);
+ $session_serialized = file_get_contents($session_file, null, null, 6);
+ flock($session_file_fp, LOCK_UN);
+ fclose($session_file_fp);
+
+ $this->log->log('SESSION: reading ' . $session_serialized . ' from ' . $session_file, Log::LEVEL_VERBOSE);
+ if ($session_serialized != '') {
+ $_SESSION['XMPPHP_BOSH'] = unserialize($session_serialized);
+ }
+ }
+
+ if (isset($_SESSION['XMPPHP_BOSH']['inactivity'])) {
+ $this->inactivity = $_SESSION['XMPPHP_BOSH']['inactivity'];
+ }
+
+ $this->lat = (time() - (isset($_SESSION['XMPPHP_BOSH']['lat']))) ? $_SESSION['XMPPHP_BOSH']['lat'] : 0;
+
+ if ($this->lat < $this->inactivity) {
+
+ if (isset($_SESSION['XMPPHP_BOSH']['RID'])) {
+ $this->rid = $_SESSION['XMPPHP_BOSH']['RID'];
+ }
+ if (isset($_SESSION['XMPPHP_BOSH']['SID'])) {
+ $this->sid = $_SESSION['XMPPHP_BOSH']['SID'];
+ }
+ if (isset($_SESSION['XMPPHP_BOSH']['authed'])) {
+ $this->authed = $_SESSION['XMPPHP_BOSH']['authed'];
+ }
+ if (isset($_SESSION['XMPPHP_BOSH']['basejid'])) {
+ $this->basejid = $_SESSION['XMPPHP_BOSH']['basejid'];
+ }
+ if (isset($_SESSION['XMPPHP_BOSH']['fulljid'])) {
+ $this->fulljid = $_SESSION['XMPPHP_BOSH']['fulljid'];
+ }
+ }
+ }
+
+ /**
+ * Get the session file
+ *
+ */
+ public function getSessionFile()
+ {
+ return sys_get_temp_dir() . '/' . $this->user . '_' . $this->server . '_session';
+ }
+
+ /**
+ * Build body
+ *
+ * @param $sub
+ * @return SimpleXMLElement|string
+ */
+ public function __buildBody($sub = null)
+ {
+
+ $xml = '<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" />';
+ $xml = new SimpleXMLElement($xml);
+ $xml->addAttribute('content', 'text/xml; charset=utf-8');
+ $xml->addAttribute('rid', $this->rid);
+ $this->rid++;
+ if ($this->sid) {
+ $xml->addAttribute('sid', $this->sid);
+ }
+
+ $xml->addAttribute('xml:lang', 'en');
+
+ if ($sub !== null) {
+
+ // Ok, so simplexml is lame
+ $parent = dom_import_simplexml($xml);
+ $content = dom_import_simplexml($sub);
+ $child = $parent->ownerDocument->importNode($content, true);
+ $parent->appendChild($child);
+ $xml = simplexml_import_dom($parent);
+ }
+
+ return $xml;
+ }
+
+ /**
+ * Send body
+ *
+ * @param $body
+ * @param $recv
+ * @return bool|string
+ * @throws Exception
+ * @throws Exception
+ */
+ public function __sendBody($body = null, $recv = true)
+ {
+
+ if (!$body) {
+ $body = $this->__buildBody();
+ }
+
+ $output = '';
+ $header = array('Accept-Encoding: gzip, deflate', 'Content-Type: text/xml; charset=utf-8');
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $this->http_server);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $body->asXML());
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_VERBOSE, 0);
+
+ if ($recv) {
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($ch);
+ if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != '200') {
+ throw new Exception('Wrong response from server!');
+ }
+
+ $this->http_buffer[] = $output;
+ }
+ curl_close($ch);
+
+ return $output;
+ }
+
+ /**
+ * Process
+ *
+ * @param $null1
+ * @param $null2
+ *
+ * null params are not used and just to statify Strict Function Declaration
+ * @return bool
+ * @throws Exception
+ * @throws Exception
+ */
+ public function __process($null1 = null, $null2 = null)
+ {
+
+ if ($this->http_buffer) {
+ $this->__parseBuffer();
+ } else {
+ $this->__sendBody();
+ $this->__parseBuffer();
+ }
+
+ $this->saveSession();
+
+ return true;
+ }
+
+ public function __parseBuffer()
+ {
+
+ while ($this->http_buffer) {
+
+ $idx = key($this->http_buffer);
+ $buffer = $this->http_buffer[$idx];
+ unset($this->http_buffer[$idx]);
+
+ if ($buffer) {
+
+ $xml = new SimpleXMLElement($buffer);
+ $children = $xml->xpath('child::node()');
+
+ foreach ($children as $child) {
+ $buff = $child->asXML();
+ $this->log->log('RECV: ' . $buff, Log::LEVEL_VERBOSE);
+ xml_parse($this->parser, $buff, false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Save session
+ *
+ */
+ public function saveSession()
+ {
+
+ $_SESSION['XMPPHP_BOSH']['RID'] = (string)$this->rid;
+ $_SESSION['XMPPHP_BOSH']['SID'] = (string)$this->sid;
+ $_SESSION['XMPPHP_BOSH']['authed'] = (boolean)$this->authed;
+ $_SESSION['XMPPHP_BOSH']['basejid'] = (string)$this->basejid;
+ $_SESSION['XMPPHP_BOSH']['fulljid'] = (string)$this->fulljid;
+ $_SESSION['XMPPHP_BOSH']['inactivity'] = (string)$this->inactivity;
+ $_SESSION['XMPPHP_BOSH']['lat'] = (string)time();
+
+ if ($this->session == 'ON_FILE') {
+
+ $session_file = $this->getSessionFile();
+ $session_file_fp = fopen($session_file, 'r');
+ flock($session_file_fp, LOCK_EX);
+ // <?php prefix used to mask the content of the session file
+ $session_serialized = '<?php ' . serialize($_SESSION);
+ file_put_contents($session_file, $session_serialized);
+ flock($session_file_fp, LOCK_UN);
+ fclose($session_file_fp);
+ }
+ }
+
+ /**
+ * Process
+ *
+ * @param $msg
+ * @param $null
+ *
+ * null param are not used and just to statify Strict Function Declaration
+ * @throws Exception
+ * @throws Exception
+ */
+ public function send($msg, $null = null)
+ {
+ $this->log->log('SEND: ' . $msg, Log::LEVEL_VERBOSE);
+ $msg = new SimpleXMLElement($msg);
+ $this->__sendBody($this->__buildBody($msg), true);
+ }
+
+ /**
+ * Reset
+ *
+ * @throws Exception
+ */
+ public function reset()
+ {
+
+ $this->xml_depth = 0;
+ unset($this->xmlobj);
+ $this->xmlobj = array();
+ $this->setupParser();
+ $body = $this->__buildBody();
+ $body->addAttribute('to', $this->host);
+ $body->addAttribute('xmpp:restart', 'true', 'urn:xmpp:xbosh');
+ $buff = '<stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">';
+ $response = $this->__sendBody($body);
+ $this->been_reset = true;
+ xml_parse($this->parser, $buff, false);
+ }
+
+ /**
+ * Disconnect
+ *
+ * @throws Exception
+ */
+ public function disconnect()
+ {
+
+ parent::disconnect();
+
+ if ($this->session == 'ON_FILE') {
+ unlink($this->getSessionFile());
+ } else {
+ $keys = array('RID', 'SID', 'authed', 'basejid', 'fulljid', 'inactivity', 'lat');
+ foreach ($keys as $key) {
+ unset($_SESSION['XMPPHP_BOSH'][$key]);
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+use Exception as ObjectException;
+
+/**
+ * XMPPHP Exception
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class Exception extends ObjectException
+{
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+/**
+ * XMPPHP Log
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class Log
+{
+ const LEVEL_ERROR = 0;
+ const LEVEL_WARNING = 1;
+ const LEVEL_INFO = 2;
+ const LEVEL_DEBUG = 3;
+ const LEVEL_VERBOSE = 4;
+
+ /**
+ * @var array
+ */
+ protected $data = array();
+
+ /**
+ * @var array
+ */
+ protected $names = array('ERROR', 'WARNING', 'INFO', 'DEBUG', 'VERBOSE');
+
+ /**
+ * @var integer
+ */
+ protected $runlevel;
+
+ /**
+ * @var boolean
+ */
+ protected $printout;
+
+ /**
+ * Constructor
+ *
+ * @param boolean $printout
+ * @param int $runlevel
+ */
+ public function __construct($printout = false, $runlevel = self::LEVEL_INFO)
+ {
+ $this->printout = (boolean)$printout;
+ $this->runlevel = (int)$runlevel;
+ }
+
+ /**
+ * Add a message to the log data array
+ * If printout in this instance is set to true, directly output the message
+ *
+ * @param string $msg
+ * @param integer $runlevel
+ */
+ public function log($msg, $runlevel = self::LEVEL_INFO)
+ {
+ $time = time();
+ #$this->data[] = array($this->runlevel, $msg, $time);
+ if ($this->printout and $runlevel <= $this->runlevel) {
+ $this->writeLine($msg, $runlevel, $time);
+ }
+ }
+
+ protected function writeLine($msg, $runlevel, $time)
+ {
+ //echo date('Y-m-d H:i:s', $time)." [".$this->names[$runlevel]."]: ".$msg."\n";
+ echo $time . " [" . $this->names[$runlevel] . "]: " . $msg . "\n";
+ flush();
+ }
+
+ /**
+ * Output the complete log.
+ * Log will be cleared if $clear = true
+ *
+ * @param boolean $clear
+ * @param integer $runlevel
+ */
+ public function printout($clear = true, $runlevel = null)
+ {
+ if ($runlevel === null) {
+ $runlevel = $this->runlevel;
+ }
+ foreach ($this->data as $data) {
+ if ($runlevel <= $data[0]) {
+ $this->writeLine($data[1], $runlevel, $data[2]);
+ }
+ }
+ if ($clear) {
+ $this->data = array();
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+/**
+ * XMPPHP Roster
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class Roster
+{
+ /**
+ * Roster array, handles contacts and presence. Indexed by jid.
+ * Contains array with potentially two indexes 'contact' and 'presence'
+ * @var array
+ */
+ protected $roster_array = array();
+
+ /**
+ * Constructor
+ * @param array $roster_array
+ */
+ public function __construct($roster_array = array())
+ {
+ if ($this->verifyRoster($roster_array)) {
+ $this->roster_array = $roster_array; //Allow for pre-population with existing roster
+ } else {
+ $this->roster_array = array();
+ }
+ }
+
+ /**
+ *
+ * Check that a given roster array is of a valid structure (empty is still valid)
+ *
+ * @param array $roster_array
+ * @return bool
+ */
+ protected function verifyRoster($roster_array)
+ {
+ #TODO once we know *what* a valid roster array looks like
+ return true;
+ }
+
+ /**
+ *
+ * Retrieve contact via jid
+ *
+ * @param string $jid
+ * @return mixed
+ */
+ public function getContact($jid)
+ {
+ if ($this->isContact($jid)) {
+ return $this->roster_array[$jid]['contact'];
+ }
+ }
+
+ /**
+ *
+ * Discover if a contact exists in the roster via jid
+ *
+ * @param string $jid
+ * @return bool
+ */
+ public function isContact($jid)
+ {
+ return (array_key_exists($jid, $this->roster_array));
+ }
+
+ /**
+ *
+ * Set presence
+ *
+ * @param string $presence
+ * @param integer $priority
+ * @param string $show
+ * @param string $status
+ */
+ public function setPresence($presence, $priority, $show, $status)
+ {
+ $presence = explode('/', $presence, 2);
+ $jid = $presence[0];
+ $resource = isset($presence[1]) ? $presence[1] : '';
+ if ($show != 'unavailable') {
+ if (!$this->isContact($jid)) {
+ $this->addContact($jid, 'not-in-roster');
+ }
+ $this->roster_array[$jid]['presence'][$resource] = array('priority' => $priority, 'show' => $show, 'status' => $status);
+ } else { //Nuke unavailable resources to save memory
+ unset($this->roster_array[$jid]['resource'][$resource]);
+ unset($this->roster_array[$jid]['presence'][$resource]);
+ }
+ }
+
+ /**
+ *
+ * Add given contact to roster
+ *
+ * @param string $jid
+ * @param string $subscription
+ * @param string $name
+ * @param array $groups
+ */
+ public function addContact($jid, $subscription, $name = '', $groups = array())
+ {
+ $contact = array('jid' => $jid, 'subscription' => $subscription, 'name' => $name, 'groups' => $groups);
+ if ($this->isContact($jid)) {
+ $this->roster_array[$jid]['contact'] = $contact;
+ } else {
+ $this->roster_array[$jid] = array('contact' => $contact);
+ }
+ }
+
+ /*
+ *
+ * Return best presence for jid
+ *
+ * @param string $jid
+ */
+
+ public function getPresence($jid)
+ {
+ $split = explode('/', $jid, 2);
+ $jid = $split[0];
+ if ($this->isContact($jid)) {
+ $current = array('resource' => '', 'active' => '', 'priority' => -129, 'show' => '', 'status' => ''); //Priorities can only be -128 = 127
+ foreach ($this->roster_array[$jid]['presence'] as $resource => $presence) {
+ //Highest available priority or just highest priority
+ if ($presence['priority'] > $current['priority'] and (($presence['show'] == "chat" or $presence['show'] == "available") or ($current['show'] != "chat" or $current['show'] != "available"))) {
+ $current = $presence;
+ $current['resource'] = $resource;
+ }
+ }
+ return $current;
+ }
+ }
+
+ /**
+ *
+ * Get roster
+ *
+ */
+ public function getRoster()
+ {
+ return $this->roster_array;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+/**
+ * XMPPHP XMLObject
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class XMLObj
+{
+ /**
+ * Tag name
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * Namespace
+ *
+ * @var string
+ */
+ public $ns;
+
+ /**
+ * Attributes
+ *
+ * @var array
+ */
+ public $attrs = array();
+
+ /**
+ * Subs?
+ *
+ * @var array
+ */
+ public $subs = array();
+
+ /**
+ * Node data
+ *
+ * @var string
+ */
+ public $data = '';
+
+ /**
+ * Constructor
+ *
+ * @param string $name
+ * @param string $ns
+ * @param array $attrs
+ * @param string $data
+ */
+ public function __construct($name, $ns = '', $attrs = array(), $data = '')
+ {
+ $this->name = strtolower($name);
+ $this->ns = $ns;
+ if (is_array($attrs) && count($attrs)) {
+ foreach ($attrs as $key => $value) {
+ $this->attrs[strtolower($key)] = $value;
+ }
+ }
+ $this->data = $data;
+ }
+
+ /**
+ * Dump this XML Object to output.
+ *
+ * @param integer $depth
+ */
+ public function printObj($depth = 0)
+ {
+ print str_repeat("\t", $depth) . $this->name . " " . $this->ns . ' ' . $this->data;
+ print "\n";
+ foreach ($this->subs as $sub) {
+ $sub->printObj($depth + 1);
+ }
+ }
+
+ /**
+ * Return this XML Object in xml notation
+ *
+ * @param string $str
+ * @return string
+ */
+ public function toString($str = '')
+ {
+ $str .= "<{$this->name} xmlns='{$this->ns}' ";
+ foreach ($this->attrs as $key => $value) {
+ if ($key != 'xmlns') {
+ $value = htmlspecialchars($value);
+ $str .= "$key='$value' ";
+ }
+ }
+ $str .= ">";
+ foreach ($this->subs as $sub) {
+ $str .= $sub->toString();
+ }
+ $body = htmlspecialchars($this->data);
+ $str .= "$body</{$this->name}>";
+ return $str;
+ }
+
+ /**
+ * Has this XML Object the given sub?
+ *
+ * @param string $name
+ * @param null $ns
+ * @return boolean
+ */
+ public function hasSub($name, $ns = null)
+ {
+ foreach ($this->subs as $sub) {
+ if (($name == "*" or $sub->name == $name) and ($ns == null or $sub->ns == $ns)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return a sub
+ *
+ * @param string $name
+ * @param string $attrs
+ * @param string $ns
+ * @return mixed
+ */
+ public function sub($name, $attrs = null, $ns = null)
+ {
+ #TODO attrs is ignored
+ foreach ($this->subs as $sub) {
+ if ($sub->name == $name and ($ns == null or $sub->ns == $ns)) {
+ return $sub;
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+/** Exception */
+require_once __DIR__ . DIRECTORY_SEPARATOR . 'Exception.php';
+
+/** XMLObj */
+require_once __DIR__ . DIRECTORY_SEPARATOR . 'XMLObj.php';
+
+/** Log */
+require_once __DIR__ . DIRECTORY_SEPARATOR . 'Log.php';
+
+
+/**
+ * XMPPHP XMLStream
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class XMLStream
+{
+ /**
+ * @var resource
+ */
+ protected $socket;
+ /**
+ * @var resource
+ */
+ protected $parser;
+ /**
+ * @var string
+ */
+ protected $buffer;
+ /**
+ * @var integer
+ */
+ protected $xml_depth = 0;
+ /**
+ * @var string
+ */
+ protected $host;
+ /**
+ * @var integer
+ */
+ protected $port;
+ /**
+ * @var string
+ */
+ protected $stream_start = '<stream>';
+ /**
+ * @var string
+ */
+ protected $stream_end = '</stream>';
+ /**
+ * @var boolean
+ */
+ protected $disconnected = false;
+ /**
+ * @var boolean
+ */
+ protected $sent_disconnect = false;
+ /**
+ * @var array
+ */
+ protected $ns_map = array();
+ /**
+ * @var array
+ */
+ protected $current_ns = array();
+ /**
+ * @var array
+ */
+ protected $xmlobj = null;
+ /**
+ * @var array
+ */
+ protected $nshandlers = array();
+ /**
+ * @var array
+ */
+ protected $xpathhandlers = array();
+ /**
+ * @var array
+ */
+ protected $idhandlers = array();
+ /**
+ * @var array
+ */
+ protected $eventhandlers = array();
+ /**
+ * @var integer
+ */
+ protected $lastid = 0;
+ /**
+ * @var string
+ */
+ protected $default_ns;
+ /**
+ * @var string[]
+ */
+ protected $until = [];
+ /**
+ * @var int[]
+ */
+ protected $until_count = [];
+ /**
+ * @var array
+ */
+ protected $until_happened = false;
+ /**
+ * @var array
+ */
+ protected $until_payload = array();
+ /**
+ * @var Log
+ */
+ protected $log;
+ /**
+ * @var boolean
+ */
+ protected $reconnect = true;
+ /**
+ * @var boolean
+ */
+ protected $been_reset = false;
+ /**
+ * @var boolean
+ */
+ protected $is_server;
+ /**
+ * @var float
+ */
+ protected $last_send = 0;
+ /**
+ * @var boolean
+ */
+ protected $use_ssl = false;
+ /**
+ * @var integer
+ */
+ protected $reconnectTimeout = 30;
+
+ /**
+ * Constructor
+ *
+ * @param string $host
+ * @param string $port
+ * @param boolean $printlog
+ * @param string $loglevel
+ * @param boolean $is_server
+ */
+ public function __construct($host = null, $port = null, $printlog = false, $loglevel = null, $is_server = false)
+ {
+ $this->reconnect = !$is_server;
+ $this->is_server = $is_server;
+ $this->host = $host;
+ $this->port = $port;
+ $this->setupParser();
+ $this->log = new Log($printlog, $loglevel);
+ }
+
+ /**
+ * Setup the XML parser
+ */
+ public function setupParser()
+ {
+ $this->parser = xml_parser_create('UTF-8');
+ xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
+ xml_set_object($this->parser, $this);
+ xml_set_element_handler($this->parser, 'startXML', 'endXML');
+ xml_set_character_data_handler($this->parser, 'charXML');
+ }
+
+ /**
+ * Destructor
+ * Cleanup connection
+ */
+ public function __destruct()
+ {
+ if (!$this->disconnected && $this->socket) {
+ $this->disconnect();
+ }
+ }
+
+ /**
+ * Disconnect from XMPP Host
+ */
+ public function disconnect()
+ {
+ $this->log->log("Disconnecting...", Log::LEVEL_VERBOSE);
+ if (false == (bool)$this->socket) {
+ return;
+ }
+ $this->reconnect = false;
+ $this->send($this->stream_end);
+ $this->sent_disconnect = true;
+ $this->processUntil('end_stream', 5);
+ $this->disconnected = true;
+ }
+
+ /**
+ * Send to socket
+ *
+ * @param string $msg
+ * @param null $timeout
+ * @return bool|int
+ * @throws Exception
+ */
+ public function send($msg, $timeout = NULL)
+ {
+
+ if (is_null($timeout)) {
+ $secs = NULL;
+ $usecs = NULL;
+ } else if ($timeout == 0) {
+ $secs = 0;
+ $usecs = 0;
+ } else {
+ $maximum = $timeout * 1000000;
+ $usecs = $maximum % 1000000;
+ $secs = floor(($maximum - $usecs) / 1000000);
+ }
+
+ $read = array();
+ $write = array($this->socket);
+ $except = array();
+
+ $select = @stream_select($read, $write, $except, $secs, $usecs);
+
+ if ($select === False) {
+ $this->log->log("ERROR sending message; reconnecting.");
+ $this->doReconnect();
+ # TODO: retry send here
+ return false;
+ } elseif ($select > 0) {
+ $this->log->log("Socket is ready; send it.", Log::LEVEL_VERBOSE);
+ } else {
+ $this->log->log("Socket is not ready; break.", Log::LEVEL_ERROR);
+ return false;
+ }
+
+ $sentbytes = @fwrite($this->socket, $msg);
+ $this->log->log("SENT: " . mb_substr($msg, 0, $sentbytes, '8bit'), Log::LEVEL_VERBOSE);
+ if ($sentbytes === FALSE) {
+ $this->log->log("ERROR sending message; reconnecting.", Log::LEVEL_ERROR);
+ $this->doReconnect();
+ return false;
+ }
+ $this->log->log("Successfully sent $sentbytes bytes.", Log::LEVEL_VERBOSE);
+ return $sentbytes;
+ }
+
+ /**
+ * Reconnect XMPP Host
+ * @throws Exception
+ */
+ public function doReconnect()
+ {
+ if (!$this->is_server) {
+ $this->log->log("Reconnecting ($this->reconnectTimeout)...", Log::LEVEL_WARNING);
+ $this->connect($this->reconnectTimeout, false, false);
+ $this->reset();
+ $this->event('reconnect');
+ }
+ }
+
+ /**
+ * Connect to XMPP Host
+ *
+ * @param integer $timeout
+ * @param boolean $persistent
+ * @param boolean $sendinit
+ * @throws Exception
+ * @throws Exception
+ */
+ public function connect($timeout = 30, $persistent = false, $sendinit = true)
+ {
+ $this->sent_disconnect = false;
+ $starttime = time();
+
+ do {
+ $this->disconnected = false;
+ $this->sent_disconnect = false;
+ if ($persistent) {
+ $conflag = STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT;
+ } else {
+ $conflag = STREAM_CLIENT_CONNECT;
+ }
+ $conntype = 'tcp';
+ if ($this->use_ssl) $conntype = 'ssl';
+ $this->log->log("Connecting to $conntype://{$this->host}:{$this->port}");
+ $this->socket = @stream_socket_client("$conntype://{$this->host}:{$this->port}", $errno, $errstr, $timeout, $conflag);
+ if (!$this->socket) {
+ $this->log->log("Could not connect.", Log::LEVEL_ERROR);
+ $this->disconnected = true;
+ # Take it easy for a few seconds
+ sleep(min($timeout, 5));
+ }
+ } while (!$this->socket && (time() - $starttime) < $timeout);
+
+ if ($this->socket) {
+ stream_set_blocking($this->socket, 1);
+ if ($sendinit) $this->send($this->stream_start);
+ } else {
+ throw new Exception("Could not connect before timeout.");
+ }
+ }
+
+ /**
+ * Reset connection
+ */
+ public function reset()
+ {
+ $this->xml_depth = 0;
+ unset($this->xmlobj);
+ $this->xmlobj = array();
+ $this->setupParser();
+ if (!$this->is_server) {
+ $this->send($this->stream_start);
+ }
+ $this->been_reset = true;
+ }
+
+ /**
+ * Event?
+ *
+ * @param string $name
+ * @param string $payload
+ */
+ public function event($name, $payload = null)
+ {
+ $this->log->log("EVENT: $name", Log::LEVEL_DEBUG);
+ foreach ($this->eventhandlers as $handler) {
+ if ($name == $handler[0]) {
+ if ($handler[2] === null) {
+ $handler[2] = $this;
+ }
+ $handler[2]->{$handler[1]}($payload);
+ }
+ }
+ foreach ($this->until as $key => $until) {
+ if (is_array($until)) {
+ if (in_array($name, $until)) {
+ $this->until_payload[$key][] = array($name, $payload);
+ if (!isset($this->until_count[$key])) {
+ $this->until_count[$key] = 0;
+ }
+ $this->until_count[$key] += 1;
+ #$this->until[$key] = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Process until a specified event or a timeout occurs
+ *
+ * @param string|array $event
+ * @param integer $timeout
+ * @return string
+ * @throws Exception
+ */
+ public function processUntil($event, $timeout = -1)
+ {
+ $start = time();
+ if (!is_array($event)) $event = array($event);
+ $this->until[] = $event;
+ end($this->until);
+ $event_key = key($this->until);
+ reset($this->until);
+ $this->until_count[$event_key] = 0;
+ while (!$this->disconnected and $this->until_count[$event_key] < 1 and (time() - $start < $timeout or $timeout == -1)) {
+ $this->__process();
+ }
+ if (array_key_exists($event_key, $this->until_payload)) {
+ $payload = $this->until_payload[$event_key];
+ unset($this->until_payload[$event_key]);
+ unset($this->until_count[$event_key]);
+ unset($this->until[$event_key]);
+ } else {
+ $payload = array();
+ }
+ return $payload;
+ }
+
+ /**
+ * Core reading tool
+ * 0 -> only read if data is immediately ready
+ * NULL -> wait forever and ever
+ * integer -> process for this amount of time
+ * @param int $maximum
+ * @return bool
+ * @throws Exception
+ */
+
+ private function __process($maximum = 5)
+ {
+
+ $remaining = $maximum;
+
+ do {
+ $starttime = (microtime(true) * 1000000);
+ $read = array($this->socket);
+ $write = array();
+ $except = array();
+ if (is_null($maximum)) {
+ $secs = NULL;
+ $usecs = NULL;
+ } else if ($maximum == 0) {
+ $secs = 0;
+ $usecs = 0;
+ } else {
+ $usecs = $remaining % 1000000;
+ $secs = floor(($remaining - $usecs) / 1000000);
+ }
+ $updated = @stream_select($read, $write, $except, $secs, $usecs);
+ if ($updated === false) {
+ $this->log->log("Error on stream_select()", Log::LEVEL_VERBOSE);
+ if ($this->reconnect) {
+ $this->doReconnect();
+ } else {
+ fclose($this->socket);
+ $this->socket = NULL;
+ return false;
+ }
+ } else if ($updated > 0) {
+ # XXX: Is this big enough?
+ $buff = @fread($this->socket, 4096);
+ if (!$buff) {
+ if ($this->reconnect) {
+ $this->doReconnect();
+ } else {
+ fclose($this->socket);
+ $this->socket = NULL;
+ return false;
+ }
+ }
+ $this->log->log("RECV: $buff", Log::LEVEL_VERBOSE);
+ xml_parse($this->parser, $buff, false);
+ } // Otherwise,
+ // $updated == 0 means no changes during timeout.
+
+ $endtime = (microtime(true) * 1000000);
+ $time_past = $endtime - $starttime;
+ $remaining = $remaining - $time_past;
+ } while (is_null($maximum) || $remaining > 0);
+ return true;
+ }
+
+ /**
+ * Return the log instance
+ *
+ * @return Log
+ */
+ public function getLog()
+ {
+ return $this->log;
+ }
+
+ /**
+ * Get next ID
+ *
+ * @return integer
+ */
+ public function getId()
+ {
+ $this->lastid++;
+ return $this->lastid;
+ }
+
+ /**
+ * Set SSL
+ * @param bool $use
+ */
+ public function useSSL($use = true)
+ {
+ $this->use_ssl = $use;
+ }
+
+ /**
+ * Add ID Handler
+ *
+ * @param integer $id
+ * @param string $pointer
+ * @param string $obj
+ */
+ public function addIdHandler($id, $pointer, $obj = null)
+ {
+ $this->idhandlers[$id] = array($pointer, $obj);
+ }
+
+ /**
+ * Add Handler
+ *
+ * @param string $name
+ * @param string $ns
+ * @param string $pointer
+ * @param string $obj
+ * @param integer $depth
+ */
+ public function addHandler($name, $ns, $pointer, $obj = null, $depth = 1)
+ {
+ #TODO deprication warning
+ $this->nshandlers[] = array($name, $ns, $pointer, $obj, $depth);
+ }
+
+ /**
+ * Add XPath Handler
+ *
+ * @param string $xpath
+ * @param string $pointer
+ * @param
+ */
+ public function addXPathHandler($xpath, $pointer, $obj = null)
+ {
+ if (preg_match_all("/\(?{[^\}]+}\)?(\/?)[^\/]+/", $xpath, $regs)) {
+ $ns_tags = $regs[0];
+ } else {
+ $ns_tags = array($xpath);
+ }
+ foreach ($ns_tags as $ns_tag) {
+ list($l, $r) = explode("}", $ns_tag);
+ if ($r != null) {
+ $xpart = array(substr($l, 1), $r);
+ } else {
+ $xpart = array(null, $l);
+ }
+ $xpath_array[] = $xpart;
+ }
+ $this->xpathhandlers[] = array($xpath_array, $pointer, $obj);
+ }
+
+ /**
+ * Add Event Handler
+ *
+ * @param $name
+ * @param string $pointer
+ * @param string $obj
+ */
+ public function addEventHandler($name, $pointer, $obj)
+ {
+ $this->eventhandlers[] = array($name, $pointer, $obj);
+ }
+
+ public function setReconnectTimeout($timeout)
+ {
+ $this->reconnectTimeout = $timeout;
+ }
+
+ /**
+ * Are we are disconnected?
+ *
+ * @return boolean
+ */
+ public function isDisconnected()
+ {
+ return $this->disconnected;
+ }
+
+ /**
+ * Process
+ *
+ */
+ public function process()
+ {
+ $this->__process(NULL);
+ }
+
+ /**
+ * Process until a timeout occurs
+ *
+ * @param integer $timeout
+ * @return string
+ * @throws Exception
+ */
+ public function processTime($timeout = NULL)
+ {
+ if (is_null($timeout)) {
+ return $this->__process(NULL);
+ } else {
+ return $this->__process($timeout * 1000000);
+ }
+ }
+
+ /**
+ * Obsolete?
+ * @param $socket
+ */
+ public function Xapply_socket($socket)
+ {
+ $this->socket = $socket;
+ }
+
+ /**
+ * XML start callback
+ *
+ * @param resource $parser
+ * @param string $name
+ * @param $attr
+ * @see xml_set_element_handler
+ */
+ public function startXML($parser, $name, $attr)
+ {
+ if ($this->been_reset) {
+ $this->been_reset = false;
+ $this->xml_depth = 0;
+ }
+ $this->xml_depth++;
+ if (array_key_exists('XMLNS', $attr)) {
+ $this->current_ns[$this->xml_depth] = $attr['XMLNS'];
+ } else {
+ $this->current_ns[$this->xml_depth] = $this->current_ns[$this->xml_depth - 1];
+ if (!$this->current_ns[$this->xml_depth]) $this->current_ns[$this->xml_depth] = $this->default_ns;
+ }
+ $ns = $this->current_ns[$this->xml_depth];
+ foreach ($attr as $key => $value) {
+ if (strstr($key, ":")) {
+ $key = explode(':', $key);
+ $key = $key[1];
+ $this->ns_map[$key] = $value;
+ }
+ }
+ if (!strstr($name, ":") === false) {
+ $name = explode(':', $name);
+ $ns = $this->ns_map[$name[0]];
+ $name = $name[1];
+ }
+ $obj = new XMLObj($name, $ns, $attr);
+ if ($this->xml_depth > 1) {
+ $this->xmlobj[$this->xml_depth - 1]->subs[] = $obj;
+ }
+ $this->xmlobj[$this->xml_depth] = $obj;
+ }
+
+ /**
+ * XML end callback
+ *
+ * @param resource $parser
+ * @param string $name
+ * @throws Exception
+ * @see xml_set_element_handler
+ *
+ */
+ public function endXML($parser, $name)
+ {
+ #$this->log->log("Ending $name", Log::LEVEL_DEBUG);
+ #print "$name\n";
+ if ($this->been_reset) {
+ $this->been_reset = false;
+ $this->xml_depth = 0;
+ }
+ $this->xml_depth--;
+ if ($this->xml_depth == 1) {
+ #clean-up old objects
+ #$found = false; #FIXME This didn't appear to be in use --Gar
+ foreach ($this->xpathhandlers as $handler) {
+ if (is_array($this->xmlobj) && array_key_exists(2, $this->xmlobj)) {
+ $searchxml = $this->xmlobj[2];
+ $nstag = array_shift($handler[0]);
+ if (($nstag[0] == null or $searchxml->ns == $nstag[0]) and ($nstag[1] == "*" or $nstag[1] == $searchxml->name)) {
+ foreach ($handler[0] as $nstag) {
+ if ($searchxml !== null and $searchxml->hasSub($nstag[1], $ns = $nstag[0])) {
+ $searchxml = $searchxml->sub($nstag[1], $ns = $nstag[0]);
+ } else {
+ $searchxml = null;
+ break;
+ }
+ }
+ if ($searchxml !== null) {
+ if ($handler[2] === null) $handler[2] = $this;
+ $this->log->log("Calling {$handler[1]}", Log::LEVEL_DEBUG);
+ $handler[2]->{$handler[1]}($this->xmlobj[2]);
+ }
+ }
+ }
+ }
+ foreach ($this->nshandlers as $handler) {
+ if ($handler[4] != 1 and array_key_exists(2, $this->xmlobj) and $this->xmlobj[2]->hasSub($handler[0])) {
+ $searchxml = $this->xmlobj[2]->sub($handler[0]);
+ } elseif (is_array($this->xmlobj) and array_key_exists(2, $this->xmlobj)) {
+ $searchxml = $this->xmlobj[2];
+ }
+ if ($searchxml !== null and $searchxml->name == $handler[0] and ($searchxml->ns == $handler[1] or (!$handler[1] and $searchxml->ns == $this->default_ns))) {
+ if ($handler[3] === null) $handler[3] = $this;
+ $this->log->log("Calling {$handler[2]}", Log::LEVEL_DEBUG);
+ $handler[3]->{$handler[2]}($this->xmlobj[2]);
+ }
+ }
+ foreach ($this->idhandlers as $id => $handler) {
+ if (array_key_exists('id', $this->xmlobj[2]->attrs) and $this->xmlobj[2]->attrs['id'] == $id) {
+ if ($handler[1] === null) $handler[1] = $this;
+ $handler[1]->{$handler[0]}($this->xmlobj[2]);
+ #id handlers are only used once
+ unset($this->idhandlers[$id]);
+ break;
+ }
+ }
+ if (is_array($this->xmlobj)) {
+ $this->xmlobj = array_slice($this->xmlobj, 0, 1);
+ if (isset($this->xmlobj[0]) && $this->xmlobj[0] instanceof XMLObj) {
+ $this->xmlobj[0]->subs = null;
+ }
+ }
+ unset($this->xmlobj[2]);
+ }
+ if ($this->xml_depth == 0 and !$this->been_reset) {
+ if (!$this->disconnected) {
+ if (!$this->sent_disconnect) {
+ $this->send($this->stream_end);
+ }
+ $this->disconnected = true;
+ $this->sent_disconnect = true;
+ fclose($this->socket);
+ if ($this->reconnect) {
+ $this->doReconnect();
+ }
+ }
+ $this->event('end_stream');
+ }
+ }
+
+ /**
+ * XML character callback
+ * @param resource $parser
+ * @param string $data
+ * @see xml_set_character_data_handler
+ *
+ */
+ public function charXML($parser, $data)
+ {
+ if (array_key_exists($this->xml_depth, $this->xmlobj)) {
+ $this->xmlobj[$this->xml_depth]->data .= $data;
+ }
+ }
+
+ /**
+ * Read from socket
+ */
+ public function read()
+ {
+ $buff = @fread($this->socket, 1024);
+ if (!$buff) {
+ if ($this->reconnect) {
+ $this->doReconnect();
+ } else {
+ fclose($this->socket);
+ return false;
+ }
+ }
+ $this->log->log("RECV: $buff", Log::LEVEL_VERBOSE);
+ xml_parse($this->parser, $buff, false);
+ }
+
+ public function time()
+ {
+ list($usec, $sec) = explode(" ", microtime());
+ return (float)$sec + (float)$usec;
+ }
+
+ public function readyToProcess()
+ {
+ $read = array($this->socket);
+ $write = array();
+ $except = array();
+ $updated = @stream_select($read, $write, $except, 0);
+ return (($updated !== false) && ($updated > 0));
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @author Alexander Birkner (https://github.com/BirknerAlex)
+ * @author zorn-v (https://github.com/zorn-v/xmpphp/)
+ * @author GNU social
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+namespace XMPPHP;
+
+/** XMPPHP_XMLStream */
+require_once __DIR__ . DIRECTORY_SEPARATOR . 'XMLStream.php';
+require_once __DIR__ . DIRECTORY_SEPARATOR . 'Roster.php';
+
+
+/**
+ * XMPPHP XMPP
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class XMPP extends XMLStream
+{
+ /**
+ * @var string
+ */
+ public $server;
+
+ /**
+ * @var string
+ */
+ public $user;
+ /**
+ * @var boolean
+ */
+ public $track_presence = true;
+ /**
+ * @var object
+ */
+ public $roster;
+ /**
+ * @var string
+ */
+ protected $password;
+ /**
+ * @var string
+ */
+ protected $resource;
+ /**
+ * @var string
+ */
+ protected $fulljid;
+ /**
+ * @var string
+ */
+ protected $basejid;
+ /**
+ * @var boolean
+ */
+ protected $authed = false;
+ protected $session_started = false;
+ /**
+ * @var boolean
+ */
+ protected $auto_subscribe = false;
+ /**
+ * @var boolean
+ */
+ protected $use_encryption = true;
+
+ /**
+ * Constructor
+ *
+ * @param string $host
+ * @param integer $port
+ * @param string $user
+ * @param string $password
+ * @param string $resource
+ * @param string $server
+ * @param boolean $printlog
+ * @param string $loglevel
+ */
+ public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null)
+ {
+ parent::__construct($host, $port, $printlog, $loglevel);
+
+ $this->user = $user;
+ $this->password = $password;
+ $this->resource = $resource;
+ if (!$server) {
+ $server = $host;
+ }
+ $this->server = $server;
+ $this->basejid = $this->user . '@' . $this->host;
+
+ $this->roster = new Roster();
+ $this->track_presence = true;
+
+ $this->stream_start = '<stream:stream to="' . $server . '" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0">';
+ $this->stream_end = '</stream:stream>';
+ $this->default_ns = 'jabber:client';
+
+ $this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler');
+ $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler');
+ $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler');
+ $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler');
+ $this->addXPathHandler('{jabber:client}message', 'message_handler');
+ $this->addXPathHandler('{jabber:client}presence', 'presence_handler');
+ $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler');
+ }
+
+ /**
+ * Turn encryption on/ff
+ *
+ * @param boolean $useEncryption
+ */
+ public function useEncryption($useEncryption = true)
+ {
+ $this->use_encryption = $useEncryption;
+ }
+
+ /**
+ * Turn on auto-authorization of subscription requests.
+ *
+ * @param boolean $autoSubscribe
+ */
+ public function autoSubscribe($autoSubscribe = true)
+ {
+ $this->auto_subscribe = $autoSubscribe;
+ }
+
+ /**
+ * Send XMPP Message
+ *
+ * @param string $to
+ * @param string $body
+ * @param string $type
+ * @param string $subject
+ * @param null $payload
+ * @throws Exception
+ */
+ public function message($to, $body, $type = 'chat', $subject = null, $payload = null)
+ {
+ if ($this->disconnected) {
+ throw new Exception('You need to connect first');
+ }
+
+ if (empty($type)) {
+ $type = 'chat';
+ }
+
+ $to = htmlspecialchars($to);
+ $body = htmlspecialchars($body);
+ $subject = htmlspecialchars($subject);
+ $subject = ($subject) ? '<subject>' . $subject . '</subject>' : '';
+ $payload = ($payload) ? $payload : '';
+ $sprintf = '<message from="%s" to="%s" type="%s">%s<body>%s</body>%s</message>';
+ $output = sprintf($sprintf, $this->fulljid, $to, $type, $subject, $body, $payload);
+ $this->send($output);
+ }
+
+ /**
+ * Set Presence
+ *
+ * @param string $status
+ * @param string $show
+ * @param string $to
+ * @param string $type
+ * @param null $priority
+ * @throws Exception
+ */
+ public function presence($status = null, $show = 'available', $to = null, $type = 'available', $priority = null)
+ {
+ if ($this->disconnected) {
+ throw new Exception('You need to connect first');
+ }
+
+ if ($type == 'available') {
+ $type = '';
+ }
+ $to = htmlspecialchars($to);
+ $status = htmlspecialchars($status);
+ if ($show == 'unavailable') {
+ $type = 'unavailable';
+ }
+
+ $out = "<presence";
+ if ($to) {
+ $out .= " to=\"$to\"";
+ }
+ if ($type) {
+ $out .= " type='$type'";
+ }
+ if ($show == 'available' and !$status and $priority !== null) {
+ $out .= "/>";
+ } else {
+ $out .= ">";
+ if ($show != 'available') {
+ $out .= "<show>$show</show>";
+ }
+ if ($status) {
+ $out .= "<status>$status</status>";
+ }
+ if ($priority !== null) {
+ $out .= "<priority>$priority</priority>";
+ }
+ $out .= "</presence>";
+ }
+
+ $this->send($out);
+ }
+
+ /**
+ * Send Auth request
+ *
+ * @param string $jid
+ */
+ public function subscribe($jid)
+ {
+ $this->send("<presence type='subscribe' to='{$jid}' from='{$this->fulljid}' />");
+ #$this->send("<presence type='subscribed' to='{$jid}' from='{$this->fulljid}' />");
+ }
+
+ /**
+ * Message handler
+ *
+ * @param string $xml
+ */
+ public function message_handler($xml)
+ {
+ if (isset($xml->attrs['type'])) {
+ $payload['type'] = $xml->attrs['type'];
+ } else {
+ $payload['type'] = 'chat';
+ }
+ $body = $xml->sub('body');
+ $payload['from'] = $xml->attrs['from'];
+ $payload['body'] = is_object($body) ? $body->data : false; // $xml->sub('body')->data;
+ $payload['xml'] = $xml;
+ $this->log->log("Message: {$payload['body']}", Log::LEVEL_DEBUG);
+ $this->event('message', $payload);
+ }
+
+ /**
+ * Presence handler
+ *
+ * @param string $xml
+ */
+ public function presence_handler($xml)
+ {
+ $payload['type'] = (isset($xml->attrs['type'])) ? $xml->attrs['type'] : 'available';
+ $payload['show'] = (isset($xml->sub('show')->data)) ? $xml->sub('show')->data : $payload['type'];
+ $payload['from'] = $xml->attrs['from'];
+ $payload['status'] = (isset($xml->sub('status')->data)) ? $xml->sub('status')->data : '';
+ $payload['priority'] = (isset($xml->sub('priority')->data)) ? intval($xml->sub('priority')->data) : 0;
+ $payload['xml'] = $xml;
+ if ($this->track_presence) {
+ $this->roster->setPresence($payload['from'], $payload['priority'], $payload['show'], $payload['status']);
+ }
+ $this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}", Log::LEVEL_DEBUG);
+ if (array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribe') {
+ if ($this->auto_subscribe) {
+ $this->send("<presence type='subscribed' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
+ $this->send("<presence type='subscribe' to='{$xml->attrs['from']}' from='{$this->fulljid}' />");
+ }
+ $this->event('subscription_requested', $payload);
+ } elseif (array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribed') {
+ $this->event('subscription_accepted', $payload);
+ } else {
+ $this->event('presence', $payload);
+ }
+ }
+
+ /**
+ * Retrieves the roster
+ *
+ */
+ public function getRoster()
+ {
+ $id = $this->getID();
+ $this->send("<iq xmlns='jabber:client' type='get' id='$id'><query xmlns='jabber:iq:roster' /></iq>");
+ }
+
+ /**
+ * Retrieves the vcard
+ * @param null $jid
+ */
+ public function getVCard($jid = null)
+ {
+ $id = $this->getID();
+ $this->addIdHandler($id, 'vcard_get_handler');
+ if ($jid) {
+ $this->send("<iq type='get' id='$id' to='$jid'><vCard xmlns='vcard-temp' /></iq>");
+ } else {
+ $this->send("<iq type='get' id='$id'><vCard xmlns='vcard-temp' /></iq>");
+ }
+ }
+
+ /**
+ * Features handler
+ *
+ * @param string $xml
+ */
+ protected function features_handler($xml)
+ {
+ if ($xml->hasSub('starttls') and $this->use_encryption) {
+ $this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>");
+ } elseif ($xml->hasSub('bind') and $this->authed) {
+ $id = $this->getId();
+ $this->addIdHandler($id, 'resource_bind_handler');
+ $this->send("<iq xmlns=\"jabber:client\" type=\"set\" id=\"$id\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>{$this->resource}</resource></bind></iq>");
+ } else {
+ $this->log->log("Attempting Auth...");
+ if ($this->password) {
+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . "</auth>");
+ } else {
+ $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
+ }
+ }
+ }
+
+ /**
+ * SASL success handler
+ *
+ * @param string $xml
+ */
+ protected function sasl_success_handler($xml)
+ {
+ $this->log->log("Auth success!");
+ $this->authed = true;
+ $this->reset();
+ }
+
+ /**
+ * SASL feature handler
+ *
+ * @param string $xml
+ * @throws Exception
+ */
+ protected function sasl_failure_handler($xml)
+ {
+ $this->log->log("Auth failed!", Log::LEVEL_ERROR);
+ $this->disconnect();
+
+ throw new Exception('Auth failed!');
+ }
+
+ /**
+ * Resource bind handler
+ *
+ * @param string $xml
+ */
+ protected function resource_bind_handler($xml)
+ {
+ if ($xml->attrs['type'] == 'result') {
+ $this->log->log("Bound to " . $xml->sub('bind')->sub('jid')->data);
+ $this->fulljid = $xml->sub('bind')->sub('jid')->data;
+ $jidarray = explode('/', $this->fulljid);
+ $this->jid = $jidarray[0];
+ }
+ $id = $this->getId();
+ $this->addIdHandler($id, 'session_start_handler');
+ $this->send("<iq xmlns='jabber:client' type='set' id='$id'><session xmlns='urn:ietf:params:xml:ns:xmpp-session' /></iq>");
+ }
+
+ /**
+ * Roster iq handler
+ * Gets all packets matching XPath "iq/{jabber:iq:roster}query'
+ *
+ * @param string $xml
+ */
+ protected function roster_iq_handler($xml)
+ {
+ $status = "result";
+ $xmlroster = $xml->sub('query');
+ foreach ($xmlroster->subs as $item) {
+ $groups = array();
+ if ($item->name == 'item') {
+ $jid = $item->attrs['jid']; //REQUIRED
+ $name = $item->attrs['name']; //MAY
+ $subscription = $item->attrs['subscription'];
+ foreach ($item->subs as $subitem) {
+ if ($subitem->name == 'group') {
+ $groups[] = $subitem->data;
+ }
+ }
+ $contacts[] = array($jid, $subscription, $name, $groups); //Store for action if no errors happen
+ } else {
+ $status = "error";
+ }
+ }
+ if ($status == "result") { //No errors, add contacts
+ foreach ($contacts as $contact) {
+ $this->roster->addContact($contact[0], $contact[1], $contact[2], $contact[3]);
+ }
+ }
+ if ($xml->attrs['type'] == 'set') {
+ $this->send("<iq type=\"reply\" id=\"{$xml->attrs['id']}\" to=\"{$xml->attrs['from']}\" />");
+ }
+ }
+
+ /**
+ * Session start handler
+ *
+ * @param string $xml
+ */
+ protected function session_start_handler($xml)
+ {
+ $this->log->log("Session started");
+ $this->session_started = true;
+ $this->event('session_start');
+ }
+
+ /**
+ * TLS proceed handler
+ *
+ * @param string $xml
+ */
+ protected function tls_proceed_handler($xml)
+ {
+ $this->log->log("Starting TLS encryption");
+ stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
+ $this->reset();
+ }
+
+ /**
+ * VCard retrieval handler
+ *
+ * @param XMLObj $xml
+ */
+ protected function vcard_get_handler($xml)
+ {
+ $vcard_array = array();
+ $vcard = $xml->sub('vcard');
+ // go through all of the sub elements and add them to the vcard array
+ foreach ($vcard->subs as $sub) {
+ if ($sub->subs) {
+ $vcard_array[$sub->name] = array();
+ foreach ($sub->subs as $sub_child) {
+ $vcard_array[$sub->name][$sub_child->name] = $sub_child->data;
+ }
+ } else {
+ $vcard_array[$sub->name] = $sub->data;
+ }
+ }
+ $vcard_array['from'] = $xml->attrs['from'];
+ $this->event('vcard', $vcard_array);
+ }
+}
--- /dev/null
+{
+ "name": "diogocomposer/xmpphp",
+ "description": "XMPP PHP Library",
+ "type": "library",
+ "keywords": ["jabber", "xmpphp", "xmpp"],
+ "license": "GPL-2.0+",
+ "authors": [
+ {
+ "name": "Nathan Fritz",
+ "email": "fritzy@netflint.net"
+ },
+ {
+ "name": "Stephan Wentz",
+ "email": "stephan@wentz.it"
+ },
+ {
+ "name": "Christian Weiske",
+ "email": "cweiske@cweiske.de"
+ },
+ {
+ "name": "Vito Tafuni",
+ "email": "vitotafuni@gmail.com"
+ },
+ {
+ "name": "Ivan Borzenkov",
+ "email": "ivan.borzenkov@gmail.com"
+ },
+ {
+ "name": "bandroidx",
+ "email": "bandroidx@gmail.com"
+ },
+ {
+ "name": "BirknerAlex",
+ "email": "alex.birkner@gmail.com"
+ },
+ {
+ "name": "Diogo Cordeiro",
+ "email": "diogo@fc.up.pt"
+ }
+ ],
+ "autoload": {
+ "psr-4": { "XMPPHP\\": "XMPPHP" }
+ },
+ "require": {
+ "php": ">=7.0.0",
+ "ext-mbstring": "*",
+ "ext-xml": "*"
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @file: XMPPHP Cli example
+ *
+ * @info: If this script doesn't work, are you running 64-bit PHP with < 5.2.6?
+ */
+
+/**
+ * Activate full error reporting
+ * error_reporting(E_ALL & E_STRICT);
+ *
+ * XMPPHP Log levels:
+ *
+ * LEVEL_ERROR = 0;
+ * LEVEL_WARNING = 1;
+ * LEVEL_INFO = 2;
+ * LEVEL_DEBUG = 3;
+ * LEVEL_VERBOSE = 4;
+ */
+
+require '../vendor/autoload.php';
+
+$conf = array(
+ 'server' => 'talk.google.com',
+ 'port' => 5222,
+ 'username' => 'username',
+ 'password' => 'password',
+ 'proto' => 'xmpphp',
+ 'domain' => 'gmail.com',
+ 'printlog' => true,
+ 'loglevel' => XMPPHP\Log::LEVEL_VERBOSE,
+);
+
+// Easy and simple for access to variables with their names
+extract($conf);
+
+$conn = new XMPPHP\XMPP($server, $port, $username, $password, $proto, $domain, $printlog, $loglevel);
+$conn->autoSubscribe();
+
+$vcard_request = array();
+
+try {
+ $conn->connect();
+
+ while (!$conn->isDisconnected()) {
+ $events = array('message', 'presence', 'end_stream', 'session_start', 'vcard');
+ $payloads = $conn->processUntil($events);
+
+ foreach ($payloads as $result) {
+ list($event, $data) = $result;
+
+ if (isset($data)) {
+ extract($data);
+ }
+
+ switch ($event) {
+
+ case 'message':
+
+ if (!$body) {
+ break;
+ }
+
+ echo str_repeat('-', 80);
+ echo "Message from: $from";
+
+ if (isset($subject)) {
+ echo "Subject: $subject";
+ }
+
+ echo $body;
+ echo str_repeat('-', 80);
+
+ $cmd = explode(' ', $body);
+ $body = "Mi no entender! '$body'";
+ $conn->message($from, $body, $type);
+
+ if (isset($cmd[0])) {
+ if ($cmd[0] == 'quit') {
+ $conn->disconnect();
+ }
+
+ if ($cmd[0] == 'break') {
+ $conn->send('</end>');
+ }
+
+ if ($cmd[0] == 'vcard') {
+ if (!isset($cmd[1])) {
+ $cmd[1] = $conn->user;
+ }
+
+ // Take a note which user requested which vcard
+ $vcard_request[$from] = $cmd[1];
+ // Request the vcard
+ $conn->getVCard($cmd[1]);
+ }
+ }
+ break;
+
+ case 'presence':
+
+ echo "Presence: $from [$show] $status\n";
+ break;
+
+ case 'session_start':
+
+ echo "Session start\n";
+ $conn->getRoster();
+ $conn->presence('Quasar!');
+ break;
+
+ case 'vcard':
+
+ $deliver = array_keys($vcard_request, $from);
+ $msg = '';
+
+ foreach ($data as $key => $item) {
+ $msg .= $key . ': ';
+
+ if (is_array($item)) {
+ $msg .= "\n";
+ foreach ($item as $subkey => $subitem) {
+ $msg .= ' ' . $subkey . ':' . $subitem . "\n";
+ }
+ } else {
+ $msg .= $item . "\n";
+ }
+ }
+
+ foreach ($deliver as $sendjid) {
+ unset($vcard_request[$sendjid]);
+ $conn->message($sendjid, $msg, 'chat');
+ }
+ break;
+ }
+ }
+ }
+} catch (XMPPHP\Exception $e) {
+ die($e->getMessage());
+}
--- /dev/null
+<?php
+
+/**
+ * @file: XMPPHP Cli example BOSH
+ *
+ * @info: If this script doesn't work, are you running 64-bit PHP with < 5.2.6?
+ */
+
+/**
+ * Activate full error reporting
+ * error_reporting(E_ALL & E_STRICT);
+ *
+ * XMPPHP Log levels:
+ *
+ * LEVEL_ERROR = 0;
+ * LEVEL_WARNING = 1;
+ * LEVEL_INFO = 2;
+ * LEVEL_DEBUG = 3;
+ * LEVEL_VERBOSE = 4;
+ */
+
+require '../vendor/autoload.php';
+
+$conf = array(
+ 'server' => 'server.tld',
+ 'port' => 5280,
+ 'username' => 'username',
+ 'password' => 'password',
+ 'proto' => 'xmpphp',
+ 'domain' => 'server.tld',
+ 'printlog' => true,
+ 'loglevel' => XMPPHP\Log::LEVEL_VERBOSE,
+);
+
+// Easy and simple for access to variables with their names
+extract($conf);
+
+$conn = new XMPPHP\BOSH($server, $port, $username, $password, $proto, $domain, $printlog, $loglevel);
+$conn->autoSubscribe();
+
+try {
+ $conn->connect('http://server.tld:5280/xmpp-httpbind');
+
+ while (!$conn->isDisconnected()) {
+ $events = array('message', 'presence', 'end_stream', 'session_start');
+ $payloads = $conn->processUntil($events);
+
+ foreach ($payloads as $result) {
+ list($event, $data) = $result;
+
+ if (isset($data)) {
+ extract($data);
+ }
+
+ switch ($event) {
+
+ case 'message':
+
+ if (!$body) {
+ break;
+ }
+
+ echo str_repeat('-', 80);
+ echo "Message from: $from";
+
+ if (isset($subject)) {
+ echo "Subject: $subject";
+ }
+
+ echo $body;
+ echo str_repeat('-', 80);
+
+ $cmd = explode(' ', $body);
+ $body = "Mi no entender! '$body'";
+ $conn->message($from, $body, $type);
+
+ if (isset($cmd[0])) {
+ if ($cmd[0] == 'quit') {
+ $conn->disconnect();
+ }
+
+ if ($cmd[0] == 'break') {
+ $conn->send('</end>');
+ }
+ }
+ break;
+
+ case 'presence':
+
+ echo "Presence: $from [$show] $status\n";
+ break;
+
+ case 'session_start':
+
+ echo "Session start\n";
+ $conn->getRoster();
+ $conn->presence('Quasar!');
+ break;
+ }
+ }
+ }
+} catch (XMPPHP\Exception $e) {
+ die($e->getMessage());
+}
--- /dev/null
+<?php
+
+/**
+ * @file: XMPPHP Send message example
+ *
+ * @info: If this script doesn't work, are you running 64-bit PHP with < 5.2.6?
+ */
+/**
+ * Activate full error reporting
+ * error_reporting(E_ALL & E_STRICT);
+ *
+ * XMPPHP Log levels:
+ *
+ * LEVEL_ERROR = 0;
+ * LEVEL_WARNING = 1;
+ * LEVEL_INFO = 2;
+ * LEVEL_DEBUG = 3;
+ * LEVEL_VERBOSE = 4;
+ */
+
+require_once __DIR__.'/../vendor/autoload.php';
+
+$conf = array(
+ 'server' => 'talk.google.com',
+ 'port' => 5222,
+ 'username' => 'username',
+ 'password' => 'password',
+ 'proto' => 'xmpphp',
+ 'domain' => 'gmail.com',
+ 'printlog' => true,
+ 'loglevel' => XMPPHP\Log::LEVEL_VERBOSE,
+);
+
+// Easy and simple for access to variables with their names
+extract($conf);
+
+$XMPP = new XMPPHP\XMPP($server, $port, $username, $password, $proto, $domain, $printlog, $loglevel);
+
+try {
+ $XMPP->connect();
+ $XMPP->processUntil('session_start', 10);
+ $XMPP->presence();
+ $XMPP->message('target.user@jabber.domain.com', 'Hello, how are you?', 'chat');
+ $XMPP->disconnect();
+} catch (XMPPHP\Exception $e) {
+ die($e->getMessage());
+}
--- /dev/null
+<?php
+
+/**
+ * @file: XMPPHP Cli example
+ *
+ * @info: If this script doesn't work, are you running 64-bit PHP with < 5.2.6?
+ */
+
+/**
+ * Activate full error reporting
+ * error_reporting(E_ALL & E_STRICT);
+ *
+ * XMPPHP Log levels:
+ *
+ * LEVEL_ERROR = 0;
+ * LEVEL_WARNING = 1;
+ * LEVEL_INFO = 2;
+ * LEVEL_DEBUG = 3;
+ * LEVEL_VERBOSE = 4;
+ */
+
+session_start();
+header('content-type', 'plain/text');
+
+require '../vendor/autoload.php';
+
+$conf = array(
+ 'server' => 'talk.google.com',
+ 'port' => 5222,
+ 'username' => 'username',
+ 'password' => 'password',
+ 'proto' => 'xmpphp',
+ 'domain' => 'gmail.com',
+ 'printlog' => true,
+ 'loglevel' => XMPPHP\Log::LEVEL_VERBOSE,
+);
+
+// Easy and simple for access to variables with their names
+extract($conf);
+
+$conn = new XMPPHP\XMPP($server, $port, $username, $password, $proto, $domain, $printlog, $loglevel);
+$conn->autoSubscribe();
+
+try {
+ if (isset($_SESSION['messages'])) {
+ foreach ($_SESSION['messages'] as $message) {
+ echo $message;
+ flush();
+ }
+ } else {
+ $_SESSION['messages'] = array();
+ }
+
+ $conn->connect('http://server.tld:5280/xmpp-httpbind', 1, true);
+ $events = array('message', 'presence', 'end_stream', 'session_start', 'vcard');
+ $payloads = $conn->processUntil($events);
+
+ foreach ($payloads as $result) {
+ list($event, $data) = $result;
+
+ if (isset($data)) {
+ extract($data);
+ }
+
+ switch ($event) {
+
+ case 'message':
+
+ if (!$body) {
+ break;
+ }
+
+ $cmd = explode(' ', $body);
+ $msg = str_repeat('-', 80);
+ $msg .= "\nMessage from: $from\n";
+
+ if (isset($subject)) {
+ $msg .= "Subject: $subject\n";
+ }
+
+ $msg .= $body . "\n";
+ $msg .= str_repeat('-', 80);
+ echo "<pre>$msg</pre>";
+
+ if (isset($cmd[0])) {
+ if ($cmd[0] == 'quit') {
+ $conn->disconnect();
+ }
+
+ if ($cmd[0] == 'break') {
+ $conn->send('</end>');
+ }
+ }
+ $_SESSION['messages'][] = $msg;
+ flush();
+ break;
+
+ case 'presence':
+
+ echo "Presence: $from [$show] $status\n";
+ break;
+
+ case 'session_start':
+
+ echo "Session start\n";
+ $conn->getRoster();
+ $conn->presence('Quasar!');
+ break;
+ }
+ }
+} catch (XMPPHP\Exception $e) {
+ die($e->getMessage());
+}
+
+$conn->saveSession();
+
+echo '<img src="http://xmpp.org/images/xmpp.png" onload="window.location.reload()" />';
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+// Get current working directory with trailing slash
+define('TESTS_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+
+// Get class directory with trailing slash
+define('CLASS_DIR', dirname(TESTS_DIR) . DIRECTORY_SEPARATOR);
+
+/** XMPPHP_LogTest */
+require_once TESTS_DIR . 'XMPPHP' . DIRECTORY_SEPARATOR . 'LogTest.php';
+
+/** XMPPHP_XMLObjTest */
+require_once TESTS_DIR . 'XMPPHP' . DIRECTORY_SEPARATOR . 'XMLObjTest.php';
+
+/** XMPPHP_XMPPTest */
+require_once TESTS_DIR . 'XMPPHP' . DIRECTORY_SEPARATOR . 'XMPPTest.php';
+
+if (!defined('PHPUnit_MAIN_METHOD')) {
+ define('PHPUnit_MAIN_METHOD', 'AllTests::main');
+}
+
+/**
+ * XMPPHP AllTests
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class AllTests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite();
+ $suite->addTestSuite('XMPPHP_LogTest');
+ $suite->addTestSuite('XMPPHP_XMLObjTest');
+ $suite->addTestSuite('XMPPHP_XMPPTest');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'AllTests::main') {
+ AllTests::main();
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+/** XMPPHP_Log */
+require_once CLASS_DIR . 'XMPPHP' . DIRECTORY_SEPARATOR . 'Log.php';
+
+/**
+ * XMPPHP LogTest
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class XMPPHP_LogTest extends PHPUnit_Framework_TestCase
+{
+ public function testPrintoutNoOutput()
+ {
+ $log = new XMPPHP_Log();
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log('test');
+ $result = ob_get_clean();
+
+ $this->assertEquals('', $result);
+ }
+
+ public function testPrintoutOutput()
+ {
+ $log = new XMPPHP_Log(true);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertContains($msg, $result);
+ }
+
+ public function testPrintoutNoOutputWithDefaultLevel()
+ {
+ $log = new XMPPHP_Log(true, XMPPHP_Log::LEVEL_ERROR);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+ }
+
+ public function testPrintoutOutputWithDefaultLevel()
+ {
+ $log = new XMPPHP_Log(true, XMPPHP_Log::LEVEL_INFO);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertContains($msg, $result);
+ }
+
+ public function testPrintoutNoOutputWithCustomLevel()
+ {
+ $log = new XMPPHP_Log(true, XMPPHP_Log::LEVEL_INFO);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg, XMPPHP_Log::LEVEL_DEBUG);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+ }
+
+ public function testPrintoutOutputWithCustomLevel()
+ {
+ $log = new XMPPHP_Log(true, XMPPHP_Log::LEVEL_INFO);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg, XMPPHP_Log::LEVEL_INFO);
+ $result = ob_get_clean();
+
+ $this->assertContains($msg, $result);
+ }
+
+ public function testExplicitPrintout()
+ {
+ $log = new XMPPHP_Log(false);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+ }
+
+ public function testExplicitPrintoutResult()
+ {
+ $log = new XMPPHP_Log(false);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+
+ ob_start();
+ $log->printout();
+ $result = ob_get_clean();
+
+ $this->assertContains($msg, $result);
+ }
+
+ public function testExplicitPrintoutClear()
+ {
+ $log = new XMPPHP_Log(false);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+
+ ob_start();
+ $log->printout();
+ $result = ob_get_clean();
+
+ $this->assertContains($msg, $result);
+
+ ob_start();
+ $log->printout();
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+ }
+
+ public function testExplicitPrintoutLevel()
+ {
+ $log = new XMPPHP_Log(false, XMPPHP_Log::LEVEL_ERROR);
+ $msg = 'I am a test log message';
+
+ ob_start();
+ $log->log($msg);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+
+ ob_start();
+ $log->printout(true, XMPPHP_Log::LEVEL_INFO);
+ $result = ob_get_clean();
+
+ $this->assertSame('', $result);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+/** XMPPHP_XMLObj */
+require_once CLASS_DIR . 'XMPPHP' . DIRECTORY_SEPARATOR . 'XMLObj.php';
+
+/**
+ * XMPPHP XMLObjectTest
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class XMPPHP_XMLObjTest extends PHPUnit_Framework_TestCase
+{
+ public function testToStringNameNamespace()
+ {
+ $xmlobj = new XMPPHP_XMLObj('testname', 'testNameSpace');
+ $expected = '<testname xmlns="testNameSpace"></testname>';
+ $result = $xmlobj->toString();
+ $this->assertSame($expected, $result);
+ }
+
+ public function testToStringNameNamespaceAttr()
+ {
+ $xmlobj = new XMPPHP_XMLObj('testName', 'testNameSpace', array('attr1' => 'valA', 'attr2' => 'valB'));
+ $expected = '<testname xmlns="testNameSpace" attr1="valA" attr2="valB"></testname>';
+ $result = $xmlobj->toString();
+ $this->assertSame($expected, $result);
+ }
+
+ public function testToStringNameNamespaceData()
+ {
+ $xmlobj = new XMPPHP_XMLObj('testName', 'testNameSpace', array(), 'I am test data');
+ $expected = '<testname xmlns="testNameSpace">I am test data</testname>';
+ $result = $xmlobj->toString();
+ $this->assertSame($expected, $result);
+ }
+
+ public function testToStringNameNamespaceSub()
+ {
+ $xmlobj = new XMPPHP_XMLObj('testName', 'testNameSpace');
+ $sub1 = new XMPPHP_XMLObj('subName', 'subNameSpace');
+ $xmlobj->subs = array($sub1);
+ $expected = '<testname xmlns="testNameSpace"><subname xmlns="subNameSpace"></subname></testname>';
+ $result = $xmlobj->toString();
+ $this->assertSame($expected, $result);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * XMPPHP: The PHP XMPP Library
+ * Copyright (C) 2008 Nathanael C. Fritz
+ * This file is part of SleekXMPP.
+ *
+ * XMPPHP 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.
+ *
+ * XMPPHP 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 XMPPHP; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @category xmpphp
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ */
+
+/** XMPPHP_XMPP */
+require_once CLASS_DIR . 'XMPPHP' . DIRECTORY_SEPARATOR . 'XMPP.php';
+
+/**
+ * XMPPHP XMPPTest
+ *
+ * @package XMPPHP
+ * @author Nathanael C. Fritz <JID: fritzy@netflint.net>
+ * @author Stephan Wentz <JID: stephan@jabber.wentz.it>
+ * @author Michael Garvin <JID: gar@netflint.net>
+ * @copyright 2008 Nathanael C. Fritz
+ * @version $Id$
+ */
+class XMPPHP_XMPPTest extends PHPUnit_Framework_TestCase
+{
+ public function testConnectException()
+ {
+ try {
+ $xmpp = new XMPPHP_XMPP('talk.google.com', 1234, 'invalidusername', 'invalidpassword', 'xmpphp', 'talk.google.com', false, XMPPHP_Log::LEVEL_VERBOSE);
+ $xmpp->useEncryption(false);
+ $xmpp->connect(10);
+ $xmpp->processUntil('session_start');
+ $xmpp->presence();
+ $xmpp->message('stephan@jabber.wentz.it', 'This is a test message!');
+ $xmpp->disconnect();
+ } catch (XMPPHP_Exception $e) {
+ return;
+ } catch (Exception $e) {
+ $this->fail('Unexpected Exception thrown: '.$e->getMessage());
+ }
+
+ $this->fail('Expected XMPPHP_Exception not thrown!');
+ }
+
+ public function testAuthException()
+ {
+ try {
+ $xmpp = new XMPPHP_XMPP('jabber.wentz.it', 5222, 'invalidusername', 'invalidpassword', 'xmpphp', 'jabber.wentz.it', true, XMPPHP_Log::LEVEL_VERBOSE);
+ $xmpp->useEncryption(false);
+ $xmpp->connect(10);
+ $xmpp->processUntil('session_start');
+ $xmpp->presence();
+ $xmpp->message('stephan@jabber.wentz.it', 'This is a test message!');
+ $xmpp->disconnect();
+ } catch (XMPPHP_Exception $e) {
+ return;
+ } catch (Exception $e) {
+ $this->fail('Unexpected Exception thrown: '.$e->getMessage());
+ }
+
+ $this->fail('Expected XMPPHP_Exception not thrown!');
+ }
+}
+++ /dev/null
-Copyright (c) 2006-2015 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.
+++ /dev/null
-# Doctrine Inflector
-
-Doctrine Inflector is a small library that can perform string manipulations
-with regard to upper-/lowercase and singular/plural forms of words.
-
-[](https://travis-ci.org/doctrine/inflector)
+++ /dev/null
-{
- "name": "doctrine/inflector",
- "type": "library",
- "description": "Common String Manipulations with regard to casing and singular/plural rules.",
- "keywords": ["string", "inflection", "singularize", "pluralize"],
- "homepage": "http://www.doctrine-project.org",
- "license": "MIT",
- "authors": [
- {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
- {"name": "Roman Borschel", "email": "roman@code-factory.org"},
- {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
- {"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
- {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
- ],
- "require": {
- "php": "^7.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^6.2"
- },
- "autoload": {
- "psr-4": { "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" }
- },
- "autoload-dev": {
- "psr-4": { "Doctrine\\Tests\\Common\\Inflector\\": "tests/Doctrine/Tests/Common/Inflector" }
- },
- "extra": {
- "branch-alias": {
- "dev-master": "1.3.x-dev"
- }
- }
-}
+++ /dev/null
-<?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\Common\Inflector;
-
-/**
- * Doctrine inflector has static methods for inflecting text.
- *
- * The methods in these classes are from several different sources collected
- * across several different php projects and several different authors. The
- * original author names and emails are not known.
- *
- * Pluralize & Singularize implementation are borrowed from CakePHP with some modifications.
- *
- * @link www.doctrine-project.org
- * @since 1.0
- * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
- * @author Jonathan H. Wage <jonwage@gmail.com>
- */
-class Inflector
-{
- /**
- * Plural inflector rules.
- *
- * @var string[][]
- */
- private static $plural = array(
- 'rules' => array(
- '/(s)tatus$/i' => '\1\2tatuses',
- '/(quiz)$/i' => '\1zes',
- '/^(ox)$/i' => '\1\2en',
- '/([m|l])ouse$/i' => '\1ice',
- '/(matr|vert|ind)(ix|ex)$/i' => '\1ices',
- '/(x|ch|ss|sh)$/i' => '\1es',
- '/([^aeiouy]|qu)y$/i' => '\1ies',
- '/(hive|gulf)$/i' => '\1s',
- '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
- '/sis$/i' => 'ses',
- '/([ti])um$/i' => '\1a',
- '/(c)riterion$/i' => '\1riteria',
- '/(p)erson$/i' => '\1eople',
- '/(m)an$/i' => '\1en',
- '/(c)hild$/i' => '\1hildren',
- '/(f)oot$/i' => '\1eet',
- '/(buffal|her|potat|tomat|volcan)o$/i' => '\1\2oes',
- '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i',
- '/us$/i' => 'uses',
- '/(alias)$/i' => '\1es',
- '/(analys|ax|cris|test|thes)is$/i' => '\1es',
- '/s$/' => 's',
- '/^$/' => '',
- '/$/' => 's',
- ),
- 'uninflected' => array(
- '.*[nrlm]ese',
- '.*deer',
- '.*fish',
- '.*measles',
- '.*ois',
- '.*pox',
- '.*sheep',
- 'people',
- 'cookie',
- 'police',
- ),
- 'irregular' => array(
- 'atlas' => 'atlases',
- 'axe' => 'axes',
- 'beef' => 'beefs',
- 'brother' => 'brothers',
- 'cafe' => 'cafes',
- 'chateau' => 'chateaux',
- 'niveau' => 'niveaux',
- 'child' => 'children',
- 'cookie' => 'cookies',
- 'corpus' => 'corpuses',
- 'cow' => 'cows',
- 'criterion' => 'criteria',
- 'curriculum' => 'curricula',
- 'demo' => 'demos',
- 'domino' => 'dominoes',
- 'echo' => 'echoes',
- 'foot' => 'feet',
- 'fungus' => 'fungi',
- 'ganglion' => 'ganglions',
- 'genie' => 'genies',
- 'genus' => 'genera',
- 'goose' => 'geese',
- 'graffito' => 'graffiti',
- 'hippopotamus' => 'hippopotami',
- 'hoof' => 'hoofs',
- 'human' => 'humans',
- 'iris' => 'irises',
- 'larva' => 'larvae',
- 'leaf' => 'leaves',
- 'loaf' => 'loaves',
- 'man' => 'men',
- 'medium' => 'media',
- 'memorandum' => 'memoranda',
- 'money' => 'monies',
- 'mongoose' => 'mongooses',
- 'motto' => 'mottoes',
- 'move' => 'moves',
- 'mythos' => 'mythoi',
- 'niche' => 'niches',
- 'nucleus' => 'nuclei',
- 'numen' => 'numina',
- 'occiput' => 'occiputs',
- 'octopus' => 'octopuses',
- 'opus' => 'opuses',
- 'ox' => 'oxen',
- 'passerby' => 'passersby',
- 'penis' => 'penises',
- 'person' => 'people',
- 'plateau' => 'plateaux',
- 'runner-up' => 'runners-up',
- 'sex' => 'sexes',
- 'soliloquy' => 'soliloquies',
- 'son-in-law' => 'sons-in-law',
- 'syllabus' => 'syllabi',
- 'testis' => 'testes',
- 'thief' => 'thieves',
- 'tooth' => 'teeth',
- 'tornado' => 'tornadoes',
- 'trilby' => 'trilbys',
- 'turf' => 'turfs',
- 'valve' => 'valves',
- 'volcano' => 'volcanoes',
- )
- );
-
- /**
- * Singular inflector rules.
- *
- * @var string[][]
- */
- private static $singular = array(
- 'rules' => array(
- '/(s)tatuses$/i' => '\1\2tatus',
- '/^(.*)(menu)s$/i' => '\1\2',
- '/(quiz)zes$/i' => '\\1',
- '/(matr)ices$/i' => '\1ix',
- '/(vert|ind)ices$/i' => '\1ex',
- '/^(ox)en/i' => '\1',
- '/(alias)(es)*$/i' => '\1',
- '/(buffal|her|potat|tomat|volcan)oes$/i' => '\1o',
- '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us',
- '/([ftw]ax)es/i' => '\1',
- '/(analys|ax|cris|test|thes)es$/i' => '\1is',
- '/(shoe|slave)s$/i' => '\1',
- '/(o)es$/i' => '\1',
- '/ouses$/' => 'ouse',
- '/([^a])uses$/' => '\1us',
- '/([m|l])ice$/i' => '\1ouse',
- '/(x|ch|ss|sh)es$/i' => '\1',
- '/(m)ovies$/i' => '\1\2ovie',
- '/(s)eries$/i' => '\1\2eries',
- '/([^aeiouy]|qu)ies$/i' => '\1y',
- '/([lr])ves$/i' => '\1f',
- '/(tive)s$/i' => '\1',
- '/(hive)s$/i' => '\1',
- '/(drive)s$/i' => '\1',
- '/(dive)s$/i' => '\1',
- '/(olive)s$/i' => '\1',
- '/([^fo])ves$/i' => '\1fe',
- '/(^analy)ses$/i' => '\1sis',
- '/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
- '/(c)riteria$/i' => '\1riterion',
- '/([ti])a$/i' => '\1um',
- '/(p)eople$/i' => '\1\2erson',
- '/(m)en$/i' => '\1an',
- '/(c)hildren$/i' => '\1\2hild',
- '/(f)eet$/i' => '\1oot',
- '/(n)ews$/i' => '\1\2ews',
- '/eaus$/' => 'eau',
- '/^(.*us)$/' => '\\1',
- '/s$/i' => '',
- ),
- 'uninflected' => array(
- '.*[nrlm]ese',
- '.*deer',
- '.*fish',
- '.*measles',
- '.*ois',
- '.*pox',
- '.*sheep',
- '.*ss',
- 'data',
- 'police',
- 'pants',
- 'clothes',
- ),
- 'irregular' => array(
- 'abuses' => 'abuse',
- 'avalanches' => 'avalanche',
- 'caches' => 'cache',
- 'criteria' => 'criterion',
- 'curves' => 'curve',
- 'emphases' => 'emphasis',
- 'foes' => 'foe',
- 'geese' => 'goose',
- 'graves' => 'grave',
- 'hoaxes' => 'hoax',
- 'media' => 'medium',
- 'neuroses' => 'neurosis',
- 'waves' => 'wave',
- 'oases' => 'oasis',
- 'valves' => 'valve',
- )
- );
-
- /**
- * Words that should not be inflected.
- *
- * @var array
- */
- private static $uninflected = array(
- '.*?media', 'Amoyese', 'audio', 'bison', 'Borghese', 'bream', 'breeches',
- 'britches', 'buffalo', 'cantus', 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'compensation', 'Congoese',
- 'contretemps', 'coreopsis', 'corps', 'data', 'debris', 'deer', 'diabetes', 'djinn', 'education', 'eland',
- 'elk', 'emoji', 'equipment', 'evidence', 'Faroese', 'feedback', 'fish', 'flounder', 'Foochowese',
- 'Furniture', 'furniture', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'gold',
- 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'jackanapes', 'jedi',
- 'Kiplingese', 'knowledge', 'Kongoese', 'love', 'Lucchese', 'Luggage', 'mackerel', 'Maltese', 'metadata',
- 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese', 'nutrition', 'offspring',
- 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'plankton', 'pliers', 'pokemon', 'police', 'Portuguese',
- 'proceedings', 'rabies', 'rain', 'rhinoceros', 'rice', 'salmon', 'Sarawakese', 'scissors', 'sea[- ]bass',
- 'series', 'Shavese', 'shears', 'sheep', 'siemens', 'species', 'staff', 'swine', 'traffic',
- 'trousers', 'trout', 'tuna', 'us', 'Vermontese', 'Wenchowese', 'wheat', 'whiting', 'wildebeest', 'Yengeese'
- );
-
- /**
- * Method cache array.
- *
- * @var array
- */
- private static $cache = array();
-
- /**
- * The initial state of Inflector so reset() works.
- *
- * @var array
- */
- private static $initialState = array();
-
- /**
- * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
- */
- public static function tableize(string $word) : string
- {
- return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word));
- }
-
- /**
- * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
- */
- public static function classify(string $word) : string
- {
- return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
- }
-
- /**
- * Camelizes a word. This uses the classify() method and turns the first character to lowercase.
- */
- public static function camelize(string $word) : string
- {
- return lcfirst(self::classify($word));
- }
-
- /**
- * Uppercases words with configurable delimeters between words.
- *
- * Takes a string and capitalizes all of the words, like PHP's built-in
- * ucwords function. This extends that behavior, however, by allowing the
- * word delimeters to be configured, rather than only separating on
- * whitespace.
- *
- * Here is an example:
- * <code>
- * <?php
- * $string = 'top-o-the-morning to all_of_you!';
- * echo \Doctrine\Common\Inflector\Inflector::ucwords($string);
- * // Top-O-The-Morning To All_of_you!
- *
- * echo \Doctrine\Common\Inflector\Inflector::ucwords($string, '-_ ');
- * // Top-O-The-Morning To All_Of_You!
- * ?>
- * </code>
- *
- * @param string $string The string to operate on.
- * @param string $delimiters A list of word separators.
- *
- * @return string The string with all delimeter-separated words capitalized.
- */
- public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
- {
- return ucwords($string, $delimiters);
- }
-
- /**
- * Clears Inflectors inflected value caches, and resets the inflection
- * rules to the initial values.
- */
- public static function reset() : void
- {
- if (empty(self::$initialState)) {
- self::$initialState = get_class_vars('Inflector');
-
- return;
- }
-
- foreach (self::$initialState as $key => $val) {
- if ($key !== 'initialState') {
- self::${$key} = $val;
- }
- }
- }
-
- /**
- * Adds custom inflection $rules, of either 'plural' or 'singular' $type.
- *
- * ### Usage:
- *
- * {{{
- * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
- * Inflector::rules('plural', array(
- * 'rules' => array('/^(inflect)ors$/i' => '\1ables'),
- * 'uninflected' => array('dontinflectme'),
- * 'irregular' => array('red' => 'redlings')
- * ));
- * }}}
- *
- * @param string $type The type of inflection, either 'plural' or 'singular'
- * @param array|iterable $rules An array of rules to be added.
- * @param boolean $reset If true, will unset default inflections for all
- * new rules that are being defined in $rules.
- *
- * @return void
- */
- public static function rules(string $type, iterable $rules, bool $reset = false) : void
- {
- foreach ($rules as $rule => $pattern) {
- if ( ! is_array($pattern)) {
- continue;
- }
-
- if ($reset) {
- self::${$type}[$rule] = $pattern;
- } else {
- self::${$type}[$rule] = ($rule === 'uninflected')
- ? array_merge($pattern, self::${$type}[$rule])
- : $pattern + self::${$type}[$rule];
- }
-
- unset($rules[$rule], self::${$type}['cache' . ucfirst($rule)]);
-
- if (isset(self::${$type}['merged'][$rule])) {
- unset(self::${$type}['merged'][$rule]);
- }
-
- if ($type === 'plural') {
- self::$cache['pluralize'] = self::$cache['tableize'] = array();
- } elseif ($type === 'singular') {
- self::$cache['singularize'] = array();
- }
- }
-
- self::${$type}['rules'] = $rules + self::${$type}['rules'];
- }
-
- /**
- * Returns a word in plural form.
- *
- * @param string $word The word in singular form.
- *
- * @return string The word in plural form.
- */
- public static function pluralize(string $word) : string
- {
- if (isset(self::$cache['pluralize'][$word])) {
- return self::$cache['pluralize'][$word];
- }
-
- if (!isset(self::$plural['merged']['irregular'])) {
- self::$plural['merged']['irregular'] = self::$plural['irregular'];
- }
-
- if (!isset(self::$plural['merged']['uninflected'])) {
- self::$plural['merged']['uninflected'] = array_merge(self::$plural['uninflected'], self::$uninflected);
- }
-
- if (!isset(self::$plural['cacheUninflected']) || !isset(self::$plural['cacheIrregular'])) {
- self::$plural['cacheUninflected'] = '(?:' . implode('|', self::$plural['merged']['uninflected']) . ')';
- self::$plural['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$plural['merged']['irregular'])) . ')';
- }
-
- if (preg_match('/(.*)\\b(' . self::$plural['cacheIrregular'] . ')$/i', $word, $regs)) {
- self::$cache['pluralize'][$word] = $regs[1] . $word[0] . substr(self::$plural['merged']['irregular'][strtolower($regs[2])], 1);
-
- return self::$cache['pluralize'][$word];
- }
-
- if (preg_match('/^(' . self::$plural['cacheUninflected'] . ')$/i', $word, $regs)) {
- self::$cache['pluralize'][$word] = $word;
-
- return $word;
- }
-
- foreach (self::$plural['rules'] as $rule => $replacement) {
- if (preg_match($rule, $word)) {
- self::$cache['pluralize'][$word] = preg_replace($rule, $replacement, $word);
-
- return self::$cache['pluralize'][$word];
- }
- }
- }
-
- /**
- * Returns a word in singular form.
- *
- * @param string $word The word in plural form.
- *
- * @return string The word in singular form.
- */
- public static function singularize(string $word) : string
- {
- if (isset(self::$cache['singularize'][$word])) {
- return self::$cache['singularize'][$word];
- }
-
- if (!isset(self::$singular['merged']['uninflected'])) {
- self::$singular['merged']['uninflected'] = array_merge(
- self::$singular['uninflected'],
- self::$uninflected
- );
- }
-
- if (!isset(self::$singular['merged']['irregular'])) {
- self::$singular['merged']['irregular'] = array_merge(
- self::$singular['irregular'],
- array_flip(self::$plural['irregular'])
- );
- }
-
- if (!isset(self::$singular['cacheUninflected']) || !isset(self::$singular['cacheIrregular'])) {
- self::$singular['cacheUninflected'] = '(?:' . implode('|', self::$singular['merged']['uninflected']) . ')';
- self::$singular['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$singular['merged']['irregular'])) . ')';
- }
-
- if (preg_match('/(.*)\\b(' . self::$singular['cacheIrregular'] . ')$/i', $word, $regs)) {
- self::$cache['singularize'][$word] = $regs[1] . $word[0] . substr(self::$singular['merged']['irregular'][strtolower($regs[2])], 1);
-
- return self::$cache['singularize'][$word];
- }
-
- if (preg_match('/^(' . self::$singular['cacheUninflected'] . ')$/i', $word, $regs)) {
- self::$cache['singularize'][$word] = $word;
-
- return $word;
- }
-
- foreach (self::$singular['rules'] as $rule => $replacement) {
- if (preg_match($rule, $word)) {
- self::$cache['singularize'][$word] = preg_replace($rule, $replacement, $word);
-
- return self::$cache['singularize'][$word];
- }
- }
-
- self::$cache['singularize'][$word] = $word;
-
- return $word;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth\Access;
-
-interface Authorizable
-{
- /**
- * Determine if the entity has a given ability.
- *
- * @param string $ability
- * @param array|mixed $arguments
- * @return bool
- */
- public function can($ability, $arguments = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth\Access;
-
-interface Gate
-{
- /**
- * Determine if a given ability has been defined.
- *
- * @param string $ability
- * @return bool
- */
- public function has($ability);
-
- /**
- * Define a new ability.
- *
- * @param string $ability
- * @param callable|string $callback
- * @return $this
- */
- public function define($ability, $callback);
-
- /**
- * Define a policy class for a given class type.
- *
- * @param string $class
- * @param string $policy
- * @return $this
- */
- public function policy($class, $policy);
-
- /**
- * Register a callback to run before all Gate checks.
- *
- * @param callable $callback
- * @return $this
- */
- public function before(callable $callback);
-
- /**
- * Register a callback to run after all Gate checks.
- *
- * @param callable $callback
- * @return $this
- */
- public function after(callable $callback);
-
- /**
- * Determine if the given ability should be granted for the current user.
- *
- * @param string $ability
- * @param array|mixed $arguments
- * @return bool
- */
- public function allows($ability, $arguments = []);
-
- /**
- * Determine if the given ability should be denied for the current user.
- *
- * @param string $ability
- * @param array|mixed $arguments
- * @return bool
- */
- public function denies($ability, $arguments = []);
-
- /**
- * Determine if all of the given abilities should be granted for the current user.
- *
- * @param iterable|string $abilities
- * @param array|mixed $arguments
- * @return bool
- */
- public function check($abilities, $arguments = []);
-
- /**
- * Determine if any one of the given abilities should be granted for the current user.
- *
- * @param iterable|string $abilities
- * @param array|mixed $arguments
- * @return bool
- */
- public function any($abilities, $arguments = []);
-
- /**
- * Determine if the given ability should be granted for the current user.
- *
- * @param string $ability
- * @param array|mixed $arguments
- * @return \Illuminate\Auth\Access\Response
- *
- * @throws \Illuminate\Auth\Access\AuthorizationException
- */
- public function authorize($ability, $arguments = []);
-
- /**
- * Get the raw result from the authorization callback.
- *
- * @param string $ability
- * @param array|mixed $arguments
- * @return mixed
- */
- public function raw($ability, $arguments = []);
-
- /**
- * Get a policy instance for a given class.
- *
- * @param object|string $class
- * @return mixed
- *
- * @throws \InvalidArgumentException
- */
- public function getPolicyFor($class);
-
- /**
- * Get a guard instance for the given user.
- *
- * @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user
- * @return static
- */
- public function forUser($user);
-
- /**
- * Get all of the defined abilities.
- *
- * @return array
- */
- public function abilities();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface Authenticatable
-{
- /**
- * Get the name of the unique identifier for the user.
- *
- * @return string
- */
- public function getAuthIdentifierName();
-
- /**
- * Get the unique identifier for the user.
- *
- * @return mixed
- */
- public function getAuthIdentifier();
-
- /**
- * Get the password for the user.
- *
- * @return string
- */
- public function getAuthPassword();
-
- /**
- * Get the token value for the "remember me" session.
- *
- * @return string
- */
- public function getRememberToken();
-
- /**
- * Set the token value for the "remember me" session.
- *
- * @param string $value
- * @return void
- */
- public function setRememberToken($value);
-
- /**
- * Get the column name for the "remember me" token.
- *
- * @return string
- */
- public function getRememberTokenName();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface CanResetPassword
-{
- /**
- * Get the e-mail address where password reset links are sent.
- *
- * @return string
- */
- public function getEmailForPasswordReset();
-
- /**
- * Send the password reset notification.
- *
- * @param string $token
- * @return void
- */
- public function sendPasswordResetNotification($token);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface Factory
-{
- /**
- * Get a guard instance by name.
- *
- * @param string|null $name
- * @return mixed
- */
- public function guard($name = null);
-
- /**
- * Set the default guard the factory should serve.
- *
- * @param string $name
- * @return void
- */
- public function shouldUse($name);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface Guard
-{
- /**
- * Determine if the current user is authenticated.
- *
- * @return bool
- */
- public function check();
-
- /**
- * Determine if the current user is a guest.
- *
- * @return bool
- */
- public function guest();
-
- /**
- * Get the currently authenticated user.
- *
- * @return \Illuminate\Contracts\Auth\Authenticatable|null
- */
- public function user();
-
- /**
- * Get the ID for the currently authenticated user.
- *
- * @return int|string|null
- */
- public function id();
-
- /**
- * Validate a user's credentials.
- *
- * @param array $credentials
- * @return bool
- */
- public function validate(array $credentials = []);
-
- /**
- * Set the current user.
- *
- * @param \Illuminate\Contracts\Auth\Authenticatable $user
- * @return void
- */
- public function setUser(Authenticatable $user);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface MustVerifyEmail
-{
- /**
- * Determine if the user has verified their email address.
- *
- * @return bool
- */
- public function hasVerifiedEmail();
-
- /**
- * Mark the given user's email as verified.
- *
- * @return bool
- */
- public function markEmailAsVerified();
-
- /**
- * Send the email verification notification.
- *
- * @return void
- */
- public function sendEmailVerificationNotification();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-use Closure;
-
-interface PasswordBroker
-{
- /**
- * Constant representing a successfully sent reminder.
- *
- * @var string
- */
- const RESET_LINK_SENT = 'passwords.sent';
-
- /**
- * Constant representing a successfully reset password.
- *
- * @var string
- */
- const PASSWORD_RESET = 'passwords.reset';
-
- /**
- * Constant representing the user not found response.
- *
- * @var string
- */
- const INVALID_USER = 'passwords.user';
-
- /**
- * Constant representing an invalid password.
- *
- * @var string
- */
- const INVALID_PASSWORD = 'passwords.password';
-
- /**
- * Constant representing an invalid token.
- *
- * @var string
- */
- const INVALID_TOKEN = 'passwords.token';
-
- /**
- * Send a password reset link to a user.
- *
- * @param array $credentials
- * @return string
- */
- public function sendResetLink(array $credentials);
-
- /**
- * Reset the password for the given token.
- *
- * @param array $credentials
- * @param \Closure $callback
- * @return mixed
- */
- public function reset(array $credentials, Closure $callback);
-
- /**
- * Set a custom password validator.
- *
- * @param \Closure $callback
- * @return void
- */
- public function validator(Closure $callback);
-
- /**
- * Determine if the passwords match for the request.
- *
- * @param array $credentials
- * @return bool
- */
- public function validateNewPassword(array $credentials);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface PasswordBrokerFactory
-{
- /**
- * Get a password broker instance by name.
- *
- * @param string|null $name
- * @return mixed
- */
- public function broker($name = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface StatefulGuard extends Guard
-{
- /**
- * Attempt to authenticate a user using the given credentials.
- *
- * @param array $credentials
- * @param bool $remember
- * @return bool
- */
- public function attempt(array $credentials = [], $remember = false);
-
- /**
- * Log a user into the application without sessions or cookies.
- *
- * @param array $credentials
- * @return bool
- */
- public function once(array $credentials = []);
-
- /**
- * Log a user into the application.
- *
- * @param \Illuminate\Contracts\Auth\Authenticatable $user
- * @param bool $remember
- * @return void
- */
- public function login(Authenticatable $user, $remember = false);
-
- /**
- * Log the given user ID into the application.
- *
- * @param mixed $id
- * @param bool $remember
- * @return \Illuminate\Contracts\Auth\Authenticatable
- */
- public function loginUsingId($id, $remember = false);
-
- /**
- * Log the given user ID into the application without sessions or cookies.
- *
- * @param mixed $id
- * @return bool
- */
- public function onceUsingId($id);
-
- /**
- * Determine if the user was authenticated via "remember me" cookie.
- *
- * @return bool
- */
- public function viaRemember();
-
- /**
- * Log the user out of the application.
- *
- * @return void
- */
- public function logout();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface SupportsBasicAuth
-{
- /**
- * Attempt to authenticate using HTTP Basic Auth.
- *
- * @param string $field
- * @param array $extraConditions
- * @return \Symfony\Component\HttpFoundation\Response|null
- */
- public function basic($field = 'email', $extraConditions = []);
-
- /**
- * Perform a stateless HTTP Basic login attempt.
- *
- * @param string $field
- * @param array $extraConditions
- * @return \Symfony\Component\HttpFoundation\Response|null
- */
- public function onceBasic($field = 'email', $extraConditions = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Auth;
-
-interface UserProvider
-{
- /**
- * Retrieve a user by their unique identifier.
- *
- * @param mixed $identifier
- * @return \Illuminate\Contracts\Auth\Authenticatable|null
- */
- public function retrieveById($identifier);
-
- /**
- * Retrieve a user by their unique identifier and "remember me" token.
- *
- * @param mixed $identifier
- * @param string $token
- * @return \Illuminate\Contracts\Auth\Authenticatable|null
- */
- public function retrieveByToken($identifier, $token);
-
- /**
- * Update the "remember me" token for the given user in storage.
- *
- * @param \Illuminate\Contracts\Auth\Authenticatable $user
- * @param string $token
- * @return void
- */
- public function updateRememberToken(Authenticatable $user, $token);
-
- /**
- * Retrieve a user by the given credentials.
- *
- * @param array $credentials
- * @return \Illuminate\Contracts\Auth\Authenticatable|null
- */
- public function retrieveByCredentials(array $credentials);
-
- /**
- * Validate a user against the given credentials.
- *
- * @param \Illuminate\Contracts\Auth\Authenticatable $user
- * @param array $credentials
- * @return bool
- */
- public function validateCredentials(Authenticatable $user, array $credentials);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Broadcasting;
-
-interface Broadcaster
-{
- /**
- * Authenticate the incoming request for a given channel.
- *
- * @param \Illuminate\Http\Request $request
- * @return mixed
- */
- public function auth($request);
-
- /**
- * Return the valid authentication response.
- *
- * @param \Illuminate\Http\Request $request
- * @param mixed $result
- * @return mixed
- */
- public function validAuthenticationResponse($request, $result);
-
- /**
- * Broadcast the given event.
- *
- * @param array $channels
- * @param string $event
- * @param array $payload
- * @return void
- */
- public function broadcast(array $channels, $event, array $payload = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Broadcasting;
-
-interface Factory
-{
- /**
- * Get a broadcaster implementation by name.
- *
- * @param string|null $name
- * @return void
- */
- public function connection($name = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Broadcasting;
-
-interface ShouldBroadcast
-{
- /**
- * Get the channels the event should broadcast on.
- *
- * @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[]
- */
- public function broadcastOn();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Broadcasting;
-
-interface ShouldBroadcastNow extends ShouldBroadcast
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Bus;
-
-interface Dispatcher
-{
- /**
- * Dispatch a command to its appropriate handler.
- *
- * @param mixed $command
- * @return mixed
- */
- public function dispatch($command);
-
- /**
- * Dispatch a command to its appropriate handler in the current process.
- *
- * @param mixed $command
- * @param mixed $handler
- * @return mixed
- */
- public function dispatchNow($command, $handler = null);
-
- /**
- * Determine if the given command has a handler.
- *
- * @param mixed $command
- * @return bool
- */
- public function hasCommandHandler($command);
-
- /**
- * Retrieve the handler for a command.
- *
- * @param mixed $command
- * @return bool|mixed
- */
- public function getCommandHandler($command);
-
- /**
- * Set the pipes commands should be piped through before dispatching.
- *
- * @param array $pipes
- * @return $this
- */
- public function pipeThrough(array $pipes);
-
- /**
- * Map a command to a handler.
- *
- * @param array $map
- * @return $this
- */
- public function map(array $map);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Bus;
-
-interface QueueingDispatcher extends Dispatcher
-{
- /**
- * Dispatch a command to its appropriate handler behind a queue.
- *
- * @param mixed $command
- * @return mixed
- */
- public function dispatchToQueue($command);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cache;
-
-interface Factory
-{
- /**
- * Get a cache store instance by name.
- *
- * @param string|null $name
- * @return \Illuminate\Contracts\Cache\Repository
- */
- public function store($name = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cache;
-
-interface Lock
-{
- /**
- * Attempt to acquire the lock.
- *
- * @param callable|null $callback
- * @return mixed
- */
- public function get($callback = null);
-
- /**
- * Attempt to acquire the lock for the given number of seconds.
- *
- * @param int $seconds
- * @param callable|null $callback
- * @return bool
- */
- public function block($seconds, $callback = null);
-
- /**
- * Release the lock.
- *
- * @return void
- */
- public function release();
-
- /**
- * Returns the current owner of the lock.
- *
- * @return string
- */
- public function owner();
-
- /**
- * Releases this lock in disregard of ownership.
- *
- * @return void
- */
- public function forceRelease();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cache;
-
-interface LockProvider
-{
- /**
- * Get a lock instance.
- *
- * @param string $name
- * @param int $seconds
- * @param string|null $owner
- * @return \Illuminate\Contracts\Cache\Lock
- */
- public function lock($name, $seconds = 0, $owner = null);
-
- /**
- * Restore a lock instance using the owner identifier.
- *
- * @param string $name
- * @param string $owner
- * @return \Illuminate\Contracts\Cache\Lock
- */
- public function restoreLock($name, $owner);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cache;
-
-use Exception;
-
-class LockTimeoutException extends Exception
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cache;
-
-use Closure;
-use Psr\SimpleCache\CacheInterface;
-
-interface Repository extends CacheInterface
-{
- /**
- * Retrieve an item from the cache and delete it.
- *
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- public function pull($key, $default = null);
-
- /**
- * Store an item in the cache.
- *
- * @param string $key
- * @param mixed $value
- * @param \DateTimeInterface|\DateInterval|int|null $ttl
- * @return bool
- */
- public function put($key, $value, $ttl = null);
-
- /**
- * Store an item in the cache if the key does not exist.
- *
- * @param string $key
- * @param mixed $value
- * @param \DateTimeInterface|\DateInterval|int|null $ttl
- * @return bool
- */
- public function add($key, $value, $ttl = null);
-
- /**
- * Increment the value of an item in the cache.
- *
- * @param string $key
- * @param mixed $value
- * @return int|bool
- */
- public function increment($key, $value = 1);
-
- /**
- * Decrement the value of an item in the cache.
- *
- * @param string $key
- * @param mixed $value
- * @return int|bool
- */
- public function decrement($key, $value = 1);
-
- /**
- * Store an item in the cache indefinitely.
- *
- * @param string $key
- * @param mixed $value
- * @return bool
- */
- public function forever($key, $value);
-
- /**
- * Get an item from the cache, or execute the given Closure and store the result.
- *
- * @param string $key
- * @param \DateTimeInterface|\DateInterval|int|null $ttl
- * @param \Closure $callback
- * @return mixed
- */
- public function remember($key, $ttl, Closure $callback);
-
- /**
- * Get an item from the cache, or execute the given Closure and store the result forever.
- *
- * @param string $key
- * @param \Closure $callback
- * @return mixed
- */
- public function sear($key, Closure $callback);
-
- /**
- * Get an item from the cache, or execute the given Closure and store the result forever.
- *
- * @param string $key
- * @param \Closure $callback
- * @return mixed
- */
- public function rememberForever($key, Closure $callback);
-
- /**
- * Remove an item from the cache.
- *
- * @param string $key
- * @return bool
- */
- public function forget($key);
-
- /**
- * Get the cache store implementation.
- *
- * @return \Illuminate\Contracts\Cache\Store
- */
- public function getStore();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cache;
-
-interface Store
-{
- /**
- * Retrieve an item from the cache by key.
- *
- * @param string|array $key
- * @return mixed
- */
- public function get($key);
-
- /**
- * Retrieve multiple items from the cache by key.
- *
- * Items not found in the cache will have a null value.
- *
- * @param array $keys
- * @return array
- */
- public function many(array $keys);
-
- /**
- * Store an item in the cache for a given number of seconds.
- *
- * @param string $key
- * @param mixed $value
- * @param int $seconds
- * @return bool
- */
- public function put($key, $value, $seconds);
-
- /**
- * Store multiple items in the cache for a given number of seconds.
- *
- * @param array $values
- * @param int $seconds
- * @return bool
- */
- public function putMany(array $values, $seconds);
-
- /**
- * Increment the value of an item in the cache.
- *
- * @param string $key
- * @param mixed $value
- * @return int|bool
- */
- public function increment($key, $value = 1);
-
- /**
- * Decrement the value of an item in the cache.
- *
- * @param string $key
- * @param mixed $value
- * @return int|bool
- */
- public function decrement($key, $value = 1);
-
- /**
- * Store an item in the cache indefinitely.
- *
- * @param string $key
- * @param mixed $value
- * @return bool
- */
- public function forever($key, $value);
-
- /**
- * Remove an item from the cache.
- *
- * @param string $key
- * @return bool
- */
- public function forget($key);
-
- /**
- * Remove all items from the cache.
- *
- * @return bool
- */
- public function flush();
-
- /**
- * Get the cache key prefix.
- *
- * @return string
- */
- public function getPrefix();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Config;
-
-interface Repository
-{
- /**
- * Determine if the given configuration value exists.
- *
- * @param string $key
- * @return bool
- */
- public function has($key);
-
- /**
- * Get the specified configuration value.
- *
- * @param array|string $key
- * @param mixed $default
- * @return mixed
- */
- public function get($key, $default = null);
-
- /**
- * Get all of the configuration items for the application.
- *
- * @return array
- */
- public function all();
-
- /**
- * Set a given configuration value.
- *
- * @param array|string $key
- * @param mixed $value
- * @return void
- */
- public function set($key, $value = null);
-
- /**
- * Prepend a value onto an array configuration value.
- *
- * @param string $key
- * @param mixed $value
- * @return void
- */
- public function prepend($key, $value);
-
- /**
- * Push a value onto an array configuration value.
- *
- * @param string $key
- * @param mixed $value
- * @return void
- */
- public function push($key, $value);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Console;
-
-interface Application
-{
- /**
- * Run an Artisan console command by name.
- *
- * @param string $command
- * @param array $parameters
- * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
- * @return int
- */
- public function call($command, array $parameters = [], $outputBuffer = null);
-
- /**
- * Get the output from the last command.
- *
- * @return string
- */
- public function output();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Console;
-
-interface Kernel
-{
- /**
- * Handle an incoming console command.
- *
- * @param \Symfony\Component\Console\Input\InputInterface $input
- * @param \Symfony\Component\Console\Output\OutputInterface|null $output
- * @return int
- */
- public function handle($input, $output = null);
-
- /**
- * Run an Artisan console command by name.
- *
- * @param string $command
- * @param array $parameters
- * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
- * @return int
- */
- public function call($command, array $parameters = [], $outputBuffer = null);
-
- /**
- * Queue an Artisan console command by name.
- *
- * @param string $command
- * @param array $parameters
- * @return \Illuminate\Foundation\Bus\PendingDispatch
- */
- public function queue($command, array $parameters = []);
-
- /**
- * Get all of the commands registered with the console.
- *
- * @return array
- */
- public function all();
-
- /**
- * Get the output for the last run command.
- *
- * @return string
- */
- public function output();
-
- /**
- * Terminate the application.
- *
- * @param \Symfony\Component\Console\Input\InputInterface $input
- * @param int $status
- * @return void
- */
- public function terminate($input, $status);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Container;
-
-use Exception;
-use Psr\Container\ContainerExceptionInterface;
-
-class BindingResolutionException extends Exception implements ContainerExceptionInterface
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Container;
-
-use Closure;
-use Psr\Container\ContainerInterface;
-
-interface Container extends ContainerInterface
-{
- /**
- * Determine if the given abstract type has been bound.
- *
- * @param string $abstract
- * @return bool
- */
- public function bound($abstract);
-
- /**
- * Alias a type to a different name.
- *
- * @param string $abstract
- * @param string $alias
- * @return void
- *
- * @throws \LogicException
- */
- public function alias($abstract, $alias);
-
- /**
- * Assign a set of tags to a given binding.
- *
- * @param array|string $abstracts
- * @param array|mixed ...$tags
- * @return void
- */
- public function tag($abstracts, $tags);
-
- /**
- * Resolve all of the bindings for a given tag.
- *
- * @param string $tag
- * @return iterable
- */
- public function tagged($tag);
-
- /**
- * Register a binding with the container.
- *
- * @param string $abstract
- * @param \Closure|string|null $concrete
- * @param bool $shared
- * @return void
- */
- public function bind($abstract, $concrete = null, $shared = false);
-
- /**
- * Register a binding if it hasn't already been registered.
- *
- * @param string $abstract
- * @param \Closure|string|null $concrete
- * @param bool $shared
- * @return void
- */
- public function bindIf($abstract, $concrete = null, $shared = false);
-
- /**
- * Register a shared binding in the container.
- *
- * @param string $abstract
- * @param \Closure|string|null $concrete
- * @return void
- */
- public function singleton($abstract, $concrete = null);
-
- /**
- * "Extend" an abstract type in the container.
- *
- * @param string $abstract
- * @param \Closure $closure
- * @return void
- *
- * @throws \InvalidArgumentException
- */
- public function extend($abstract, Closure $closure);
-
- /**
- * Register an existing instance as shared in the container.
- *
- * @param string $abstract
- * @param mixed $instance
- * @return mixed
- */
- public function instance($abstract, $instance);
-
- /**
- * Add a contextual binding to the container.
- *
- * @param string $concrete
- * @param string $abstract
- * @param \Closure|string $implementation
- * @return void
- */
- public function addContextualBinding($concrete, $abstract, $implementation);
-
- /**
- * Define a contextual binding.
- *
- * @param string|array $concrete
- * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
- */
- public function when($concrete);
-
- /**
- * Get a closure to resolve the given type from the container.
- *
- * @param string $abstract
- * @return \Closure
- */
- public function factory($abstract);
-
- /**
- * Flush the container of all bindings and resolved instances.
- *
- * @return void
- */
- public function flush();
-
- /**
- * Resolve the given type from the container.
- *
- * @param string $abstract
- * @param array $parameters
- * @return mixed
- *
- * @throws \Illuminate\Contracts\Container\BindingResolutionException
- */
- public function make($abstract, array $parameters = []);
-
- /**
- * Call the given Closure / class@method and inject its dependencies.
- *
- * @param callable|string $callback
- * @param array $parameters
- * @param string|null $defaultMethod
- * @return mixed
- */
- public function call($callback, array $parameters = [], $defaultMethod = null);
-
- /**
- * Determine if the given abstract type has been resolved.
- *
- * @param string $abstract
- * @return bool
- */
- public function resolved($abstract);
-
- /**
- * Register a new resolving callback.
- *
- * @param \Closure|string $abstract
- * @param \Closure|null $callback
- * @return void
- */
- public function resolving($abstract, Closure $callback = null);
-
- /**
- * Register a new after resolving callback.
- *
- * @param \Closure|string $abstract
- * @param \Closure|null $callback
- * @return void
- */
- public function afterResolving($abstract, Closure $callback = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Container;
-
-interface ContextualBindingBuilder
-{
- /**
- * Define the abstract target that depends on the context.
- *
- * @param string $abstract
- * @return $this
- */
- public function needs($abstract);
-
- /**
- * Define the implementation for the contextual binding.
- *
- * @param \Closure|string $implementation
- * @return void
- */
- public function give($implementation);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cookie;
-
-interface Factory
-{
- /**
- * Create a new cookie instance.
- *
- * @param string $name
- * @param string $value
- * @param int $minutes
- * @param string|null $path
- * @param string|null $domain
- * @param bool|null $secure
- * @param bool $httpOnly
- * @param bool $raw
- * @param string|null $sameSite
- * @return \Symfony\Component\HttpFoundation\Cookie
- */
- public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null);
-
- /**
- * Create a cookie that lasts "forever" (five years).
- *
- * @param string $name
- * @param string $value
- * @param string|null $path
- * @param string|null $domain
- * @param bool|null $secure
- * @param bool $httpOnly
- * @param bool $raw
- * @param string|null $sameSite
- * @return \Symfony\Component\HttpFoundation\Cookie
- */
- public function forever($name, $value, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null);
-
- /**
- * Expire the given cookie.
- *
- * @param string $name
- * @param string|null $path
- * @param string|null $domain
- * @return \Symfony\Component\HttpFoundation\Cookie
- */
- public function forget($name, $path = null, $domain = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Cookie;
-
-interface QueueingFactory extends Factory
-{
- /**
- * Queue a cookie to send with the next response.
- *
- * @param array $parameters
- * @return void
- */
- public function queue(...$parameters);
-
- /**
- * Remove a cookie from the queue.
- *
- * @param string $name
- */
- public function unqueue($name);
-
- /**
- * Get the cookies which have been queued for the next request.
- *
- * @return array
- */
- public function getQueuedCookies();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Database\Events;
-
-interface MigrationEvent
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Database;
-
-class ModelIdentifier
-{
- /**
- * The class name of the model.
- *
- * @var string
- */
- public $class;
-
- /**
- * The unique identifier of the model.
- *
- * This may be either a single ID or an array of IDs.
- *
- * @var mixed
- */
- public $id;
-
- /**
- * The relationships loaded on the model.
- *
- * @var array
- */
- public $relations;
-
- /**
- * The connection name of the model.
- *
- * @var string|null
- */
- public $connection;
-
- /**
- * Create a new model identifier.
- *
- * @param string $class
- * @param mixed $id
- * @param array $relations
- * @param mixed $connection
- * @return void
- */
- public function __construct($class, $id, array $relations, $connection)
- {
- $this->id = $id;
- $this->class = $class;
- $this->relations = $relations;
- $this->connection = $connection;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Debug;
-
-use Exception;
-
-interface ExceptionHandler
-{
- /**
- * Report or log an exception.
- *
- * @param \Exception $e
- * @return void
- */
- public function report(Exception $e);
-
- /**
- * Determine if the exception should be reported.
- *
- * @param \Exception $e
- * @return bool
- */
- public function shouldReport(Exception $e);
-
- /**
- * Render an exception into an HTTP response.
- *
- * @param \Illuminate\Http\Request $request
- * @param \Exception $e
- * @return \Symfony\Component\HttpFoundation\Response
- */
- public function render($request, Exception $e);
-
- /**
- * Render an exception to the console.
- *
- * @param \Symfony\Component\Console\Output\OutputInterface $output
- * @param \Exception $e
- * @return void
- */
- public function renderForConsole($output, Exception $e);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Encryption;
-
-use RuntimeException;
-
-class DecryptException extends RuntimeException
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Encryption;
-
-use RuntimeException;
-
-class EncryptException extends RuntimeException
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Encryption;
-
-interface Encrypter
-{
- /**
- * Encrypt the given value.
- *
- * @param mixed $value
- * @param bool $serialize
- * @return string
- *
- * @throws \Illuminate\Contracts\Encryption\EncryptException
- */
- public function encrypt($value, $serialize = true);
-
- /**
- * Decrypt the given value.
- *
- * @param string $payload
- * @param bool $unserialize
- * @return mixed
- *
- * @throws \Illuminate\Contracts\Encryption\DecryptException
- */
- public function decrypt($payload, $unserialize = true);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Events;
-
-interface Dispatcher
-{
- /**
- * Register an event listener with the dispatcher.
- *
- * @param string|array $events
- * @param mixed $listener
- * @return void
- */
- public function listen($events, $listener);
-
- /**
- * Determine if a given event has listeners.
- *
- * @param string $eventName
- * @return bool
- */
- public function hasListeners($eventName);
-
- /**
- * Register an event subscriber with the dispatcher.
- *
- * @param object|string $subscriber
- * @return void
- */
- public function subscribe($subscriber);
-
- /**
- * Dispatch an event until the first non-null response is returned.
- *
- * @param string|object $event
- * @param mixed $payload
- * @return array|null
- */
- public function until($event, $payload = []);
-
- /**
- * Dispatch an event and call the listeners.
- *
- * @param string|object $event
- * @param mixed $payload
- * @param bool $halt
- * @return array|null
- */
- public function dispatch($event, $payload = [], $halt = false);
-
- /**
- * Register an event and payload to be fired later.
- *
- * @param string $event
- * @param array $payload
- * @return void
- */
- public function push($event, $payload = []);
-
- /**
- * Flush a set of pushed events.
- *
- * @param string $event
- * @return void
- */
- public function flush($event);
-
- /**
- * Remove a set of listeners from the dispatcher.
- *
- * @param string $event
- * @return void
- */
- public function forget($event);
-
- /**
- * Forget all of the queued listeners.
- *
- * @return void
- */
- public function forgetPushed();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Filesystem;
-
-interface Cloud extends Filesystem
-{
- /**
- * Get the URL for the file at the given path.
- *
- * @param string $path
- * @return string
- */
- public function url($path);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Filesystem;
-
-interface Factory
-{
- /**
- * Get a filesystem implementation.
- *
- * @param string|null $name
- * @return \Illuminate\Contracts\Filesystem\Filesystem
- */
- public function disk($name = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Filesystem;
-
-use Exception;
-
-class FileExistsException extends Exception
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Filesystem;
-
-use Exception;
-
-class FileNotFoundException extends Exception
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Filesystem;
-
-interface Filesystem
-{
- /**
- * The public visibility setting.
- *
- * @var string
- */
- const VISIBILITY_PUBLIC = 'public';
-
- /**
- * The private visibility setting.
- *
- * @var string
- */
- const VISIBILITY_PRIVATE = 'private';
-
- /**
- * Determine if a file exists.
- *
- * @param string $path
- * @return bool
- */
- public function exists($path);
-
- /**
- * Get the contents of a file.
- *
- * @param string $path
- * @return string
- *
- * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
- */
- public function get($path);
-
- /**
- * Get a resource to read the file.
- *
- * @param string $path
- * @return resource|null The path resource or null on failure.
- *
- * @throws FileNotFoundException
- */
- public function readStream($path);
-
- /**
- * Write the contents of a file.
- *
- * @param string $path
- * @param string|resource $contents
- * @param mixed $options
- * @return bool
- */
- public function put($path, $contents, $options = []);
-
- /**
- * Write a new file using a stream.
- *
- * @param string $path
- * @param resource $resource
- * @param array $options
- * @return bool
- *
- * @throws \InvalidArgumentException If $resource is not a file handle.
- * @throws FileExistsException
- */
- public function writeStream($path, $resource, array $options = []);
-
- /**
- * Get the visibility for the given path.
- *
- * @param string $path
- * @return string
- */
- public function getVisibility($path);
-
- /**
- * Set the visibility for the given path.
- *
- * @param string $path
- * @param string $visibility
- * @return bool
- */
- public function setVisibility($path, $visibility);
-
- /**
- * Prepend to a file.
- *
- * @param string $path
- * @param string $data
- * @return bool
- */
- public function prepend($path, $data);
-
- /**
- * Append to a file.
- *
- * @param string $path
- * @param string $data
- * @return bool
- */
- public function append($path, $data);
-
- /**
- * Delete the file at a given path.
- *
- * @param string|array $paths
- * @return bool
- */
- public function delete($paths);
-
- /**
- * Copy a file to a new location.
- *
- * @param string $from
- * @param string $to
- * @return bool
- */
- public function copy($from, $to);
-
- /**
- * Move a file to a new location.
- *
- * @param string $from
- * @param string $to
- * @return bool
- */
- public function move($from, $to);
-
- /**
- * Get the file size of a given file.
- *
- * @param string $path
- * @return int
- */
- public function size($path);
-
- /**
- * Get the file's last modification time.
- *
- * @param string $path
- * @return int
- */
- public function lastModified($path);
-
- /**
- * Get an array of all files in a directory.
- *
- * @param string|null $directory
- * @param bool $recursive
- * @return array
- */
- public function files($directory = null, $recursive = false);
-
- /**
- * Get all of the files from the given directory (recursive).
- *
- * @param string|null $directory
- * @return array
- */
- public function allFiles($directory = null);
-
- /**
- * Get all of the directories within a given directory.
- *
- * @param string|null $directory
- * @param bool $recursive
- * @return array
- */
- public function directories($directory = null, $recursive = false);
-
- /**
- * Get all (recursive) of the directories within a given directory.
- *
- * @param string|null $directory
- * @return array
- */
- public function allDirectories($directory = null);
-
- /**
- * Create a directory.
- *
- * @param string $path
- * @return bool
- */
- public function makeDirectory($path);
-
- /**
- * Recursively delete a directory.
- *
- * @param string $directory
- * @return bool
- */
- public function deleteDirectory($directory);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Foundation;
-
-use Closure;
-use Illuminate\Contracts\Container\Container;
-
-interface Application extends Container
-{
- /**
- * Get the version number of the application.
- *
- * @return string
- */
- public function version();
-
- /**
- * Get the base path of the Laravel installation.
- *
- * @return string
- */
- public function basePath();
-
- /**
- * Get the path to the bootstrap directory.
- *
- * @param string $path Optionally, a path to append to the bootstrap path
- * @return string
- */
- public function bootstrapPath($path = '');
-
- /**
- * Get the path to the application configuration files.
- *
- * @param string $path Optionally, a path to append to the config path
- * @return string
- */
- public function configPath($path = '');
-
- /**
- * Get the path to the database directory.
- *
- * @param string $path Optionally, a path to append to the database path
- * @return string
- */
- public function databasePath($path = '');
-
- /**
- * Get the path to the environment file directory.
- *
- * @return string
- */
- public function environmentPath();
-
- /**
- * Get the path to the resources directory.
- *
- * @param string $path
- * @return string
- */
- public function resourcePath($path = '');
-
- /**
- * Get the path to the storage directory.
- *
- * @return string
- */
- public function storagePath();
-
- /**
- * Get or check the current application environment.
- *
- * @param string|array $environments
- * @return string|bool
- */
- public function environment(...$environments);
-
- /**
- * Determine if the application is running in the console.
- *
- * @return bool
- */
- public function runningInConsole();
-
- /**
- * Determine if the application is running unit tests.
- *
- * @return bool
- */
- public function runningUnitTests();
-
- /**
- * Determine if the application is currently down for maintenance.
- *
- * @return bool
- */
- public function isDownForMaintenance();
-
- /**
- * Register all of the configured providers.
- *
- * @return void
- */
- public function registerConfiguredProviders();
-
- /**
- * Register a service provider with the application.
- *
- * @param \Illuminate\Support\ServiceProvider|string $provider
- * @param bool $force
- * @return \Illuminate\Support\ServiceProvider
- */
- public function register($provider, $force = false);
-
- /**
- * Register a deferred provider and service.
- *
- * @param string $provider
- * @param string|null $service
- * @return void
- */
- public function registerDeferredProvider($provider, $service = null);
-
- /**
- * Resolve a service provider instance from the class name.
- *
- * @param string $provider
- * @return \Illuminate\Support\ServiceProvider
- */
- public function resolveProvider($provider);
-
- /**
- * Boot the application's service providers.
- *
- * @return void
- */
- public function boot();
-
- /**
- * Register a new boot listener.
- *
- * @param callable $callback
- * @return void
- */
- public function booting($callback);
-
- /**
- * Register a new "booted" listener.
- *
- * @param callable $callback
- * @return void
- */
- public function booted($callback);
-
- /**
- * Run the given array of bootstrap classes.
- *
- * @param array $bootstrappers
- * @return void
- */
- public function bootstrapWith(array $bootstrappers);
-
- /**
- * Determine if the application configuration is cached.
- *
- * @return bool
- */
- public function configurationIsCached();
-
- /**
- * Detect the application's current environment.
- *
- * @param \Closure $callback
- * @return string
- */
- public function detectEnvironment(Closure $callback);
-
- /**
- * Get the environment file the application is using.
- *
- * @return string
- */
- public function environmentFile();
-
- /**
- * Get the fully qualified path to the environment file.
- *
- * @return string
- */
- public function environmentFilePath();
-
- /**
- * Get the path to the configuration cache file.
- *
- * @return string
- */
- public function getCachedConfigPath();
-
- /**
- * Get the path to the cached services.php file.
- *
- * @return string
- */
- public function getCachedServicesPath();
-
- /**
- * Get the path to the cached packages.php file.
- *
- * @return string
- */
- public function getCachedPackagesPath();
-
- /**
- * Get the path to the routes cache file.
- *
- * @return string
- */
- public function getCachedRoutesPath();
-
- /**
- * Get the current application locale.
- *
- * @return string
- */
- public function getLocale();
-
- /**
- * Get the application namespace.
- *
- * @return string
- *
- * @throws \RuntimeException
- */
- public function getNamespace();
-
- /**
- * Get the registered service provider instances if any exist.
- *
- * @param \Illuminate\Support\ServiceProvider|string $provider
- * @return array
- */
- public function getProviders($provider);
-
- /**
- * Determine if the application has been bootstrapped before.
- *
- * @return bool
- */
- public function hasBeenBootstrapped();
-
- /**
- * Load and boot all of the remaining deferred providers.
- *
- * @return void
- */
- public function loadDeferredProviders();
-
- /**
- * Set the environment file to be loaded during bootstrapping.
- *
- * @param string $file
- * @return $this
- */
- public function loadEnvironmentFrom($file);
-
- /**
- * Determine if the application routes are cached.
- *
- * @return bool
- */
- public function routesAreCached();
-
- /**
- * Set the current application locale.
- *
- * @param string $locale
- * @return void
- */
- public function setLocale($locale);
-
- /**
- * Determine if middleware has been disabled for the application.
- *
- * @return bool
- */
- public function shouldSkipMiddleware();
-
- /**
- * Terminate the application.
- *
- * @return void
- */
- public function terminate();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Hashing;
-
-interface Hasher
-{
- /**
- * Get information about the given hashed value.
- *
- * @param string $hashedValue
- * @return array
- */
- public function info($hashedValue);
-
- /**
- * Hash the given value.
- *
- * @param string $value
- * @param array $options
- * @return string
- */
- public function make($value, array $options = []);
-
- /**
- * Check the given plain value against a hash.
- *
- * @param string $value
- * @param string $hashedValue
- * @param array $options
- * @return bool
- */
- public function check($value, $hashedValue, array $options = []);
-
- /**
- * Check if the given hash has been hashed using the given options.
- *
- * @param string $hashedValue
- * @param array $options
- * @return bool
- */
- public function needsRehash($hashedValue, array $options = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Http;
-
-interface Kernel
-{
- /**
- * Bootstrap the application for HTTP requests.
- *
- * @return void
- */
- public function bootstrap();
-
- /**
- * Handle an incoming HTTP request.
- *
- * @param \Symfony\Component\HttpFoundation\Request $request
- * @return \Symfony\Component\HttpFoundation\Response
- */
- public function handle($request);
-
- /**
- * Perform any final actions for the request lifecycle.
- *
- * @param \Symfony\Component\HttpFoundation\Request $request
- * @param \Symfony\Component\HttpFoundation\Response $response
- * @return void
- */
- public function terminate($request, $response);
-
- /**
- * Get the Laravel application instance.
- *
- * @return \Illuminate\Contracts\Foundation\Application
- */
- public function getApplication();
-}
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) Taylor Otwell
-
-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.
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Mail;
-
-interface MailQueue
-{
- /**
- * Queue a new e-mail message for sending.
- *
- * @param string|array|\Illuminate\Contracts\Mail\Mailable $view
- * @param string|null $queue
- * @return mixed
- */
- public function queue($view, $queue = null);
-
- /**
- * Queue a new e-mail message for sending after (n) seconds.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param string|array|\Illuminate\Contracts\Mail\Mailable $view
- * @param string|null $queue
- * @return mixed
- */
- public function later($delay, $view, $queue = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Mail;
-
-use Illuminate\Contracts\Queue\Factory as Queue;
-
-interface Mailable
-{
- /**
- * Send the message using the given mailer.
- *
- * @param \Illuminate\Contracts\Mail\Mailer $mailer
- * @return void
- */
- public function send(Mailer $mailer);
-
- /**
- * Queue the given message.
- *
- * @param \Illuminate\Contracts\Queue\Factory $queue
- * @return mixed
- */
- public function queue(Queue $queue);
-
- /**
- * Deliver the queued message after the given delay.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param \Illuminate\Contracts\Queue\Factory $queue
- * @return mixed
- */
- public function later($delay, Queue $queue);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Mail;
-
-interface Mailer
-{
- /**
- * Begin the process of mailing a mailable class instance.
- *
- * @param mixed $users
- * @return \Illuminate\Mail\PendingMail
- */
- public function to($users);
-
- /**
- * Begin the process of mailing a mailable class instance.
- *
- * @param mixed $users
- * @return \Illuminate\Mail\PendingMail
- */
- public function bcc($users);
-
- /**
- * Send a new message with only a raw text part.
- *
- * @param string $text
- * @param mixed $callback
- * @return void
- */
- public function raw($text, $callback);
-
- /**
- * Send a new message using a view.
- *
- * @param string|array|\Illuminate\Contracts\Mail\Mailable $view
- * @param array $data
- * @param \Closure|string|null $callback
- * @return void
- */
- public function send($view, array $data = [], $callback = null);
-
- /**
- * Get the array of failed recipients.
- *
- * @return array
- */
- public function failures();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Notifications;
-
-interface Dispatcher
-{
- /**
- * Send the given notification to the given notifiable entities.
- *
- * @param \Illuminate\Support\Collection|array|mixed $notifiables
- * @param mixed $notification
- * @return void
- */
- public function send($notifiables, $notification);
-
- /**
- * Send the given notification immediately.
- *
- * @param \Illuminate\Support\Collection|array|mixed $notifiables
- * @param mixed $notification
- * @return void
- */
- public function sendNow($notifiables, $notification);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Notifications;
-
-interface Factory
-{
- /**
- * Get a channel instance by name.
- *
- * @param string|null $name
- * @return mixed
- */
- public function channel($name = null);
-
- /**
- * Send the given notification to the given notifiable entities.
- *
- * @param \Illuminate\Support\Collection|array|mixed $notifiables
- * @param mixed $notification
- * @return void
- */
- public function send($notifiables, $notification);
-
- /**
- * Send the given notification immediately.
- *
- * @param \Illuminate\Support\Collection|array|mixed $notifiables
- * @param mixed $notification
- * @return void
- */
- public function sendNow($notifiables, $notification);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Pagination;
-
-interface LengthAwarePaginator extends Paginator
-{
- /**
- * Create a range of pagination URLs.
- *
- * @param int $start
- * @param int $end
- * @return array
- */
- public function getUrlRange($start, $end);
-
- /**
- * Determine the total number of items in the data store.
- *
- * @return int
- */
- public function total();
-
- /**
- * Get the page number of the last available page.
- *
- * @return int
- */
- public function lastPage();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Pagination;
-
-interface Paginator
-{
- /**
- * Get the URL for a given page.
- *
- * @param int $page
- * @return string
- */
- public function url($page);
-
- /**
- * Add a set of query string values to the paginator.
- *
- * @param array|string $key
- * @param string|null $value
- * @return $this
- */
- public function appends($key, $value = null);
-
- /**
- * Get / set the URL fragment to be appended to URLs.
- *
- * @param string|null $fragment
- * @return $this|string
- */
- public function fragment($fragment = null);
-
- /**
- * The URL for the next page, or null.
- *
- * @return string|null
- */
- public function nextPageUrl();
-
- /**
- * Get the URL for the previous page, or null.
- *
- * @return string|null
- */
- public function previousPageUrl();
-
- /**
- * Get all of the items being paginated.
- *
- * @return array
- */
- public function items();
-
- /**
- * Get the "index" of the first item being paginated.
- *
- * @return int
- */
- public function firstItem();
-
- /**
- * Get the "index" of the last item being paginated.
- *
- * @return int
- */
- public function lastItem();
-
- /**
- * Determine how many items are being shown per page.
- *
- * @return int
- */
- public function perPage();
-
- /**
- * Determine the current page being paginated.
- *
- * @return int
- */
- public function currentPage();
-
- /**
- * Determine if there are enough items to split into multiple pages.
- *
- * @return bool
- */
- public function hasPages();
-
- /**
- * Determine if there is more items in the data store.
- *
- * @return bool
- */
- public function hasMorePages();
-
- /**
- * Determine if the list of items is empty or not.
- *
- * @return bool
- */
- public function isEmpty();
-
- /**
- * Determine if the list of items is not empty.
- *
- * @return bool
- */
- public function isNotEmpty();
-
- /**
- * Render the paginator using a given view.
- *
- * @param string|null $view
- * @param array $data
- * @return string
- */
- public function render($view = null, $data = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Pipeline;
-
-interface Hub
-{
- /**
- * Send an object through one of the available pipelines.
- *
- * @param mixed $object
- * @param string|null $pipeline
- * @return mixed
- */
- public function pipe($object, $pipeline = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Pipeline;
-
-use Closure;
-
-interface Pipeline
-{
- /**
- * Set the traveler object being sent on the pipeline.
- *
- * @param mixed $traveler
- * @return $this
- */
- public function send($traveler);
-
- /**
- * Set the stops of the pipeline.
- *
- * @param dynamic|array $stops
- * @return $this
- */
- public function through($stops);
-
- /**
- * Set the method to call on the stops.
- *
- * @param string $method
- * @return $this
- */
- public function via($method);
-
- /**
- * Run the pipeline with a final destination callback.
- *
- * @param \Closure $destination
- * @return mixed
- */
- public function then(Closure $destination);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-use InvalidArgumentException;
-
-class EntityNotFoundException extends InvalidArgumentException
-{
- /**
- * Create a new exception instance.
- *
- * @param string $type
- * @param mixed $id
- * @return void
- */
- public function __construct($type, $id)
- {
- $id = (string) $id;
-
- parent::__construct("Queueable entity [{$type}] not found for ID [{$id}].");
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface EntityResolver
-{
- /**
- * Resolve the entity for the given ID.
- *
- * @param string $type
- * @param mixed $id
- * @return mixed
- */
- public function resolve($type, $id);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface Factory
-{
- /**
- * Resolve a queue connection instance.
- *
- * @param string|null $name
- * @return \Illuminate\Contracts\Queue\Queue
- */
- public function connection($name = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface Job
-{
- /**
- * Get the job identifier.
- *
- * @return string
- */
- public function getJobId();
-
- /**
- * Get the decoded body of the job.
- *
- * @return array
- */
- public function payload();
-
- /**
- * Fire the job.
- *
- * @return void
- */
- public function fire();
-
- /**
- * Release the job back into the queue.
- *
- * Accepts a delay specified in seconds.
- *
- * @param int $delay
- * @return void
- */
- public function release($delay = 0);
-
- /**
- * Determine if the job was released back into the queue.
- *
- * @return bool
- */
- public function isReleased();
-
- /**
- * Delete the job from the queue.
- *
- * @return void
- */
- public function delete();
-
- /**
- * Determine if the job has been deleted.
- *
- * @return bool
- */
- public function isDeleted();
-
- /**
- * Determine if the job has been deleted or released.
- *
- * @return bool
- */
- public function isDeletedOrReleased();
-
- /**
- * Get the number of times the job has been attempted.
- *
- * @return int
- */
- public function attempts();
-
- /**
- * Determine if the job has been marked as a failure.
- *
- * @return bool
- */
- public function hasFailed();
-
- /**
- * Mark the job as "failed".
- *
- * @return void
- */
- public function markAsFailed();
-
- /**
- * Delete the job, call the "failed" method, and raise the failed job event.
- *
- * @param \Throwable|null $e
- * @return void
- */
- public function fail($e = null);
-
- /**
- * Get the number of times to attempt a job.
- *
- * @return int|null
- */
- public function maxTries();
-
- /**
- * Get the number of seconds the job can run.
- *
- * @return int|null
- */
- public function timeout();
-
- /**
- * Get the timestamp indicating when the job should timeout.
- *
- * @return int|null
- */
- public function timeoutAt();
-
- /**
- * Get the name of the queued job class.
- *
- * @return string
- */
- public function getName();
-
- /**
- * Get the resolved name of the queued job class.
- *
- * Resolves the name of "wrapped" jobs such as class-based handlers.
- *
- * @return string
- */
- public function resolveName();
-
- /**
- * Get the name of the connection the job belongs to.
- *
- * @return string
- */
- public function getConnectionName();
-
- /**
- * Get the name of the queue the job belongs to.
- *
- * @return string
- */
- public function getQueue();
-
- /**
- * Get the raw body string for the job.
- *
- * @return string
- */
- public function getRawBody();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface Monitor
-{
- /**
- * Register a callback to be executed on every iteration through the queue loop.
- *
- * @param mixed $callback
- * @return void
- */
- public function looping($callback);
-
- /**
- * Register a callback to be executed when a job fails after the maximum amount of retries.
- *
- * @param mixed $callback
- * @return void
- */
- public function failing($callback);
-
- /**
- * Register a callback to be executed when a daemon queue is stopping.
- *
- * @param mixed $callback
- * @return void
- */
- public function stopping($callback);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface Queue
-{
- /**
- * Get the size of the queue.
- *
- * @param string|null $queue
- * @return int
- */
- public function size($queue = null);
-
- /**
- * Push a new job onto the queue.
- *
- * @param string|object $job
- * @param mixed $data
- * @param string|null $queue
- * @return mixed
- */
- public function push($job, $data = '', $queue = null);
-
- /**
- * Push a new job onto the queue.
- *
- * @param string $queue
- * @param string|object $job
- * @param mixed $data
- * @return mixed
- */
- public function pushOn($queue, $job, $data = '');
-
- /**
- * Push a raw payload onto the queue.
- *
- * @param string $payload
- * @param string|null $queue
- * @param array $options
- * @return mixed
- */
- public function pushRaw($payload, $queue = null, array $options = []);
-
- /**
- * Push a new job onto the queue after a delay.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param string|object $job
- * @param mixed $data
- * @param string|null $queue
- * @return mixed
- */
- public function later($delay, $job, $data = '', $queue = null);
-
- /**
- * Push a new job onto the queue after a delay.
- *
- * @param string $queue
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param string|object $job
- * @param mixed $data
- * @return mixed
- */
- public function laterOn($queue, $delay, $job, $data = '');
-
- /**
- * Push an array of jobs onto the queue.
- *
- * @param array $jobs
- * @param mixed $data
- * @param string|null $queue
- * @return mixed
- */
- public function bulk($jobs, $data = '', $queue = null);
-
- /**
- * Pop the next job off of the queue.
- *
- * @param string $queue
- * @return \Illuminate\Contracts\Queue\Job|null
- */
- public function pop($queue = null);
-
- /**
- * Get the connection name for the queue.
- *
- * @return string
- */
- public function getConnectionName();
-
- /**
- * Set the connection name for the queue.
- *
- * @param string $name
- * @return $this
- */
- public function setConnectionName($name);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface QueueableCollection
-{
- /**
- * Get the type of the entities being queued.
- *
- * @return string|null
- */
- public function getQueueableClass();
-
- /**
- * Get the identifiers for all of the entities.
- *
- * @return array
- */
- public function getQueueableIds();
-
- /**
- * Get the relationships of the entities being queued.
- *
- * @return array
- */
- public function getQueueableRelations();
-
- /**
- * Get the connection of the entities being queued.
- *
- * @return string|null
- */
- public function getQueueableConnection();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface QueueableEntity
-{
- /**
- * Get the queueable identity for the entity.
- *
- * @return mixed
- */
- public function getQueueableId();
-
- /**
- * Get the relationships for the entity.
- *
- * @return array
- */
- public function getQueueableRelations();
-
- /**
- * Get the connection of the entity.
- *
- * @return string|null
- */
- public function getQueueableConnection();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Queue;
-
-interface ShouldQueue
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Redis;
-
-use Closure;
-
-interface Connection
-{
- /**
- * Subscribe to a set of given channels for messages.
- *
- * @param array|string $channels
- * @param \Closure $callback
- * @return void
- */
- public function subscribe($channels, Closure $callback);
-
- /**
- * Subscribe to a set of given channels with wildcards.
- *
- * @param array|string $channels
- * @param \Closure $callback
- * @return void
- */
- public function psubscribe($channels, Closure $callback);
-
- /**
- * Run a command against the Redis database.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function command($method, array $parameters = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Redis;
-
-interface Factory
-{
- /**
- * Get a Redis connection by name.
- *
- * @param string|null $name
- * @return \Illuminate\Redis\Connections\Connection
- */
- public function connection($name = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Redis;
-
-use Exception;
-
-class LimiterTimeoutException extends Exception
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Routing;
-
-interface BindingRegistrar
-{
- /**
- * Add a new route parameter binder.
- *
- * @param string $key
- * @param string|callable $binder
- * @return void
- */
- public function bind($key, $binder);
-
- /**
- * Get the binding callback for a given binding.
- *
- * @param string $key
- * @return \Closure
- */
- public function getBindingCallback($key);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Routing;
-
-interface Registrar
-{
- /**
- * Register a new GET route with the router.
- *
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function get($uri, $action);
-
- /**
- * Register a new POST route with the router.
- *
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function post($uri, $action);
-
- /**
- * Register a new PUT route with the router.
- *
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function put($uri, $action);
-
- /**
- * Register a new DELETE route with the router.
- *
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function delete($uri, $action);
-
- /**
- * Register a new PATCH route with the router.
- *
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function patch($uri, $action);
-
- /**
- * Register a new OPTIONS route with the router.
- *
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function options($uri, $action);
-
- /**
- * Register a new route with the given verbs.
- *
- * @param array|string $methods
- * @param string $uri
- * @param \Closure|array|string|callable $action
- * @return \Illuminate\Routing\Route
- */
- public function match($methods, $uri, $action);
-
- /**
- * Route a resource to a controller.
- *
- * @param string $name
- * @param string $controller
- * @param array $options
- * @return \Illuminate\Routing\PendingResourceRegistration
- */
- public function resource($name, $controller, array $options = []);
-
- /**
- * Create a route group with shared attributes.
- *
- * @param array $attributes
- * @param \Closure|string $routes
- * @return void
- */
- public function group(array $attributes, $routes);
-
- /**
- * Substitute the route bindings onto the route.
- *
- * @param \Illuminate\Routing\Route $route
- * @return \Illuminate\Routing\Route
- */
- public function substituteBindings($route);
-
- /**
- * Substitute the implicit Eloquent model bindings for the route.
- *
- * @param \Illuminate\Routing\Route $route
- * @return void
- */
- public function substituteImplicitBindings($route);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Routing;
-
-interface ResponseFactory
-{
- /**
- * Create a new response instance.
- *
- * @param string $content
- * @param int $status
- * @param array $headers
- * @return \Illuminate\Http\Response
- */
- public function make($content = '', $status = 200, array $headers = []);
-
- /**
- * Create a new "no content" response.
- *
- * @param int $status
- * @param array $headers
- * @return \Illuminate\Http\Response
- */
- public function noContent($status = 204, array $headers = []);
-
- /**
- * Create a new response for a given view.
- *
- * @param string $view
- * @param array $data
- * @param int $status
- * @param array $headers
- * @return \Illuminate\Http\Response
- */
- public function view($view, $data = [], $status = 200, array $headers = []);
-
- /**
- * Create a new JSON response instance.
- *
- * @param string|array|object $data
- * @param int $status
- * @param array $headers
- * @param int $options
- * @return \Illuminate\Http\JsonResponse
- */
- public function json($data = [], $status = 200, array $headers = [], $options = 0);
-
- /**
- * Create a new JSONP response instance.
- *
- * @param string $callback
- * @param string|array|object $data
- * @param int $status
- * @param array $headers
- * @param int $options
- * @return \Illuminate\Http\JsonResponse
- */
- public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0);
-
- /**
- * Create a new streamed response instance.
- *
- * @param \Closure $callback
- * @param int $status
- * @param array $headers
- * @return \Symfony\Component\HttpFoundation\StreamedResponse
- */
- public function stream($callback, $status = 200, array $headers = []);
-
- /**
- * Create a new streamed response instance as a file download.
- *
- * @param \Closure $callback
- * @param string|null $name
- * @param array $headers
- * @param string|null $disposition
- * @return \Symfony\Component\HttpFoundation\StreamedResponse
- */
- public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment');
-
- /**
- * Create a new file download response.
- *
- * @param \SplFileInfo|string $file
- * @param string|null $name
- * @param array $headers
- * @param string|null $disposition
- * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
- */
- public function download($file, $name = null, array $headers = [], $disposition = 'attachment');
-
- /**
- * Return the raw contents of a binary file.
- *
- * @param \SplFileInfo|string $file
- * @param array $headers
- * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
- */
- public function file($file, array $headers = []);
-
- /**
- * Create a new redirect response to the given path.
- *
- * @param string $path
- * @param int $status
- * @param array $headers
- * @param bool|null $secure
- * @return \Illuminate\Http\RedirectResponse
- */
- public function redirectTo($path, $status = 302, $headers = [], $secure = null);
-
- /**
- * Create a new redirect response to a named route.
- *
- * @param string $route
- * @param array $parameters
- * @param int $status
- * @param array $headers
- * @return \Illuminate\Http\RedirectResponse
- */
- public function redirectToRoute($route, $parameters = [], $status = 302, $headers = []);
-
- /**
- * Create a new redirect response to a controller action.
- *
- * @param string $action
- * @param array $parameters
- * @param int $status
- * @param array $headers
- * @return \Illuminate\Http\RedirectResponse
- */
- public function redirectToAction($action, $parameters = [], $status = 302, $headers = []);
-
- /**
- * Create a new redirect response, while putting the current URL in the session.
- *
- * @param string $path
- * @param int $status
- * @param array $headers
- * @param bool|null $secure
- * @return \Illuminate\Http\RedirectResponse
- */
- public function redirectGuest($path, $status = 302, $headers = [], $secure = null);
-
- /**
- * Create a new redirect response to the previously intended location.
- *
- * @param string $default
- * @param int $status
- * @param array $headers
- * @param bool|null $secure
- * @return \Illuminate\Http\RedirectResponse
- */
- public function redirectToIntended($default = '/', $status = 302, $headers = [], $secure = null);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Routing;
-
-interface UrlGenerator
-{
- /**
- * Get the current URL for the request.
- *
- * @return string
- */
- public function current();
-
- /**
- * Get the URL for the previous request.
- *
- * @param mixed $fallback
- * @return string
- */
- public function previous($fallback = false);
-
- /**
- * Generate an absolute URL to the given path.
- *
- * @param string $path
- * @param mixed $extra
- * @param bool|null $secure
- * @return string
- */
- public function to($path, $extra = [], $secure = null);
-
- /**
- * Generate a secure, absolute URL to the given path.
- *
- * @param string $path
- * @param array $parameters
- * @return string
- */
- public function secure($path, $parameters = []);
-
- /**
- * Generate the URL to an application asset.
- *
- * @param string $path
- * @param bool|null $secure
- * @return string
- */
- public function asset($path, $secure = null);
-
- /**
- * Get the URL to a named route.
- *
- * @param string $name
- * @param mixed $parameters
- * @param bool $absolute
- * @return string
- *
- * @throws \InvalidArgumentException
- */
- public function route($name, $parameters = [], $absolute = true);
-
- /**
- * Get the URL to a controller action.
- *
- * @param string|array $action
- * @param mixed $parameters
- * @param bool $absolute
- * @return string
- */
- public function action($action, $parameters = [], $absolute = true);
-
- /**
- * Set the root controller namespace.
- *
- * @param string $rootNamespace
- * @return $this
- */
- public function setRootControllerNamespace($rootNamespace);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Routing;
-
-interface UrlRoutable
-{
- /**
- * Get the value of the model's route key.
- *
- * @return mixed
- */
- public function getRouteKey();
-
- /**
- * Get the route key for the model.
- *
- * @return string
- */
- public function getRouteKeyName();
-
- /**
- * Retrieve the model for a bound value.
- *
- * @param mixed $value
- * @return \Illuminate\Database\Eloquent\Model|null
- */
- public function resolveRouteBinding($value);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Session;
-
-interface Session
-{
- /**
- * Get the name of the session.
- *
- * @return string
- */
- public function getName();
-
- /**
- * Get the current session ID.
- *
- * @return string
- */
- public function getId();
-
- /**
- * Set the session ID.
- *
- * @param string $id
- * @return void
- */
- public function setId($id);
-
- /**
- * Start the session, reading the data from a handler.
- *
- * @return bool
- */
- public function start();
-
- /**
- * Save the session data to storage.
- *
- * @return void
- */
- public function save();
-
- /**
- * Get all of the session data.
- *
- * @return array
- */
- public function all();
-
- /**
- * Checks if a key exists.
- *
- * @param string|array $key
- * @return bool
- */
- public function exists($key);
-
- /**
- * Checks if an a key is present and not null.
- *
- * @param string|array $key
- * @return bool
- */
- public function has($key);
-
- /**
- * Get an item from the session.
- *
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- public function get($key, $default = null);
-
- /**
- * Put a key / value pair or array of key / value pairs in the session.
- *
- * @param string|array $key
- * @param mixed $value
- * @return void
- */
- public function put($key, $value = null);
-
- /**
- * Get the CSRF token value.
- *
- * @return string
- */
- public function token();
-
- /**
- * Remove an item from the session, returning its value.
- *
- * @param string $key
- * @return mixed
- */
- public function remove($key);
-
- /**
- * Remove one or many items from the session.
- *
- * @param string|array $keys
- * @return void
- */
- public function forget($keys);
-
- /**
- * Remove all of the items from the session.
- *
- * @return void
- */
- public function flush();
-
- /**
- * Generate a new session ID for the session.
- *
- * @param bool $destroy
- * @return bool
- */
- public function migrate($destroy = false);
-
- /**
- * Determine if the session has been started.
- *
- * @return bool
- */
- public function isStarted();
-
- /**
- * Get the previous URL from the session.
- *
- * @return string|null
- */
- public function previousUrl();
-
- /**
- * Set the "previous" URL in the session.
- *
- * @param string $url
- * @return void
- */
- public function setPreviousUrl($url);
-
- /**
- * Get the session handler instance.
- *
- * @return \SessionHandlerInterface
- */
- public function getHandler();
-
- /**
- * Determine if the session handler needs a request.
- *
- * @return bool
- */
- public function handlerNeedsRequest();
-
- /**
- * Set the request on the handler instance.
- *
- * @param \Illuminate\Http\Request $request
- * @return void
- */
- public function setRequestOnHandler($request);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface Arrayable
-{
- /**
- * Get the instance as an array.
- *
- * @return array
- */
- public function toArray();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface DeferrableProvider
-{
- /**
- * Get the services provided by the provider.
- *
- * @return array
- */
- public function provides();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface Htmlable
-{
- /**
- * Get content as a string of HTML.
- *
- * @return string
- */
- public function toHtml();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface Jsonable
-{
- /**
- * Convert the object to its JSON representation.
- *
- * @param int $options
- * @return string
- */
- public function toJson($options = 0);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface MessageBag extends Arrayable
-{
- /**
- * Get the keys present in the message bag.
- *
- * @return array
- */
- public function keys();
-
- /**
- * Add a message to the bag.
- *
- * @param string $key
- * @param string $message
- * @return $this
- */
- public function add($key, $message);
-
- /**
- * Merge a new array of messages into the bag.
- *
- * @param \Illuminate\Contracts\Support\MessageProvider|array $messages
- * @return $this
- */
- public function merge($messages);
-
- /**
- * Determine if messages exist for a given key.
- *
- * @param string|array $key
- * @return bool
- */
- public function has($key);
-
- /**
- * Get the first message from the bag for a given key.
- *
- * @param string|null $key
- * @param string|null $format
- * @return string
- */
- public function first($key = null, $format = null);
-
- /**
- * Get all of the messages from the bag for a given key.
- *
- * @param string $key
- * @param string|null $format
- * @return array
- */
- public function get($key, $format = null);
-
- /**
- * Get all of the messages for every key in the bag.
- *
- * @param string|null $format
- * @return array
- */
- public function all($format = null);
-
- /**
- * Get the raw messages in the container.
- *
- * @return array
- */
- public function getMessages();
-
- /**
- * Get the default message format.
- *
- * @return string
- */
- public function getFormat();
-
- /**
- * Set the default message format.
- *
- * @param string $format
- * @return $this
- */
- public function setFormat($format = ':message');
-
- /**
- * Determine if the message bag has any messages.
- *
- * @return bool
- */
- public function isEmpty();
-
- /**
- * Determine if the message bag has any messages.
- *
- * @return bool
- */
- public function isNotEmpty();
-
- /**
- * Get the number of messages in the container.
- *
- * @return int
- */
- public function count();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface MessageProvider
-{
- /**
- * Get the messages for the instance.
- *
- * @return \Illuminate\Contracts\Support\MessageBag
- */
- public function getMessageBag();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface Renderable
-{
- /**
- * Get the evaluated contents of the object.
- *
- * @return string
- */
- public function render();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Support;
-
-interface Responsable
-{
- /**
- * Create an HTTP response that represents the object.
- *
- * @param \Illuminate\Http\Request $request
- * @return \Symfony\Component\HttpFoundation\Response
- */
- public function toResponse($request);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Translation;
-
-interface HasLocalePreference
-{
- /**
- * Get the preferred locale of the entity.
- *
- * @return string|null
- */
- public function preferredLocale();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Translation;
-
-interface Loader
-{
- /**
- * Load the messages for the given locale.
- *
- * @param string $locale
- * @param string $group
- * @param string|null $namespace
- * @return array
- */
- public function load($locale, $group, $namespace = null);
-
- /**
- * Add a new namespace to the loader.
- *
- * @param string $namespace
- * @param string $hint
- * @return void
- */
- public function addNamespace($namespace, $hint);
-
- /**
- * Add a new JSON path to the loader.
- *
- * @param string $path
- * @return void
- */
- public function addJsonPath($path);
-
- /**
- * Get an array of all the registered namespaces.
- *
- * @return array
- */
- public function namespaces();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Translation;
-
-interface Translator
-{
- /**
- * Get the translation for a given key.
- *
- * @param string $key
- * @param array $replace
- * @param string|null $locale
- * @return mixed
- */
- public function trans($key, array $replace = [], $locale = null);
-
- /**
- * Get a translation according to an integer value.
- *
- * @param string $key
- * @param int|array|\Countable $number
- * @param array $replace
- * @param string|null $locale
- * @return string
- */
- public function transChoice($key, $number, array $replace = [], $locale = null);
-
- /**
- * Get the default locale being used.
- *
- * @return string
- */
- public function getLocale();
-
- /**
- * Set the default locale.
- *
- * @param string $locale
- * @return void
- */
- public function setLocale($locale);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Validation;
-
-interface Factory
-{
- /**
- * Create a new Validator instance.
- *
- * @param array $data
- * @param array $rules
- * @param array $messages
- * @param array $customAttributes
- * @return \Illuminate\Contracts\Validation\Validator
- */
- public function make(array $data, array $rules, array $messages = [], array $customAttributes = []);
-
- /**
- * Register a custom validator extension.
- *
- * @param string $rule
- * @param \Closure|string $extension
- * @param string|null $message
- * @return void
- */
- public function extend($rule, $extension, $message = null);
-
- /**
- * Register a custom implicit validator extension.
- *
- * @param string $rule
- * @param \Closure|string $extension
- * @param string|null $message
- * @return void
- */
- public function extendImplicit($rule, $extension, $message = null);
-
- /**
- * Register a custom implicit validator message replacer.
- *
- * @param string $rule
- * @param \Closure|string $replacer
- * @return void
- */
- public function replacer($rule, $replacer);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Validation;
-
-interface ImplicitRule extends Rule
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Validation;
-
-interface Rule
-{
- /**
- * Determine if the validation rule passes.
- *
- * @param string $attribute
- * @param mixed $value
- * @return bool
- */
- public function passes($attribute, $value);
-
- /**
- * Get the validation error message.
- *
- * @return string|array
- */
- public function message();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Validation;
-
-interface ValidatesWhenResolved
-{
- /**
- * Validate the given class instance.
- *
- * @return void
- */
- public function validateResolved();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Validation;
-
-use Illuminate\Contracts\Support\MessageProvider;
-
-interface Validator extends MessageProvider
-{
- /**
- * Run the validator's rules against its data.
- *
- * @return array
- */
- public function validate();
-
- /**
- * Get the attributes and values that were validated.
- *
- * @return array
- */
- public function validated();
-
- /**
- * Determine if the data fails the validation rules.
- *
- * @return bool
- */
- public function fails();
-
- /**
- * Get the failed validation rules.
- *
- * @return array
- */
- public function failed();
-
- /**
- * Add conditions to a given field based on a Closure.
- *
- * @param string|array $attribute
- * @param string|array $rules
- * @param callable $callback
- * @return $this
- */
- public function sometimes($attribute, $rules, callable $callback);
-
- /**
- * Add an after validation callback.
- *
- * @param callable|string $callback
- * @return $this
- */
- public function after($callback);
-
- /**
- * Get all of the validation error messages.
- *
- * @return \Illuminate\Support\MessageBag
- */
- public function errors();
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\View;
-
-interface Engine
-{
- /**
- * Get the evaluated contents of the view.
- *
- * @param string $path
- * @param array $data
- * @return string
- */
- public function get($path, array $data = []);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\View;
-
-interface Factory
-{
- /**
- * Determine if a given view exists.
- *
- * @param string $view
- * @return bool
- */
- public function exists($view);
-
- /**
- * Get the evaluated view contents for the given path.
- *
- * @param string $path
- * @param \Illuminate\Contracts\Support\Arrayable|array $data
- * @param array $mergeData
- * @return \Illuminate\Contracts\View\View
- */
- public function file($path, $data = [], $mergeData = []);
-
- /**
- * Get the evaluated view contents for the given view.
- *
- * @param string $view
- * @param \Illuminate\Contracts\Support\Arrayable|array $data
- * @param array $mergeData
- * @return \Illuminate\Contracts\View\View
- */
- public function make($view, $data = [], $mergeData = []);
-
- /**
- * Add a piece of shared data to the environment.
- *
- * @param array|string $key
- * @param mixed $value
- * @return mixed
- */
- public function share($key, $value = null);
-
- /**
- * Register a view composer event.
- *
- * @param array|string $views
- * @param \Closure|string $callback
- * @return array
- */
- public function composer($views, $callback);
-
- /**
- * Register a view creator event.
- *
- * @param array|string $views
- * @param \Closure|string $callback
- * @return array
- */
- public function creator($views, $callback);
-
- /**
- * Add a new namespace to the loader.
- *
- * @param string $namespace
- * @param string|array $hints
- * @return $this
- */
- public function addNamespace($namespace, $hints);
-
- /**
- * Replace the namespace hints for the given namespace.
- *
- * @param string $namespace
- * @param string|array $hints
- * @return $this
- */
- public function replaceNamespace($namespace, $hints);
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\View;
-
-use Illuminate\Contracts\Support\Renderable;
-
-interface View extends Renderable
-{
- /**
- * Get the name of the view.
- *
- * @return string
- */
- public function name();
-
- /**
- * Add a piece of data to the view.
- *
- * @param string|array $key
- * @param mixed $value
- * @return $this
- */
- public function with($key, $value = null);
-
- /**
- * Get the array of view data.
- *
- * @return array
- */
- public function getData();
-}
+++ /dev/null
-{
- "name": "illuminate/contracts",
- "description": "The Illuminate Contracts package.",
- "license": "MIT",
- "homepage": "https://laravel.com",
- "support": {
- "issues": "https://github.com/laravel/framework/issues",
- "source": "https://github.com/laravel/framework"
- },
- "authors": [
- {
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
- }
- ],
- "require": {
- "php": "^7.1.3",
- "psr/container": "^1.0",
- "psr/simple-cache": "^1.0"
- },
- "autoload": {
- "psr-4": {
- "Illuminate\\Contracts\\": ""
- }
- },
- "extra": {
- "branch-alias": {
- "dev-master": "5.8-dev"
- }
- },
- "config": {
- "sort-packages": true
- },
- "minimum-stability": "dev"
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-class AggregateServiceProvider extends ServiceProvider
-{
- /**
- * The provider class names.
- *
- * @var array
- */
- protected $providers = [];
-
- /**
- * An array of the service provider instances.
- *
- * @var array
- */
- protected $instances = [];
-
- /**
- * Register the service provider.
- *
- * @return void
- */
- public function register()
- {
- $this->instances = [];
-
- foreach ($this->providers as $provider) {
- $this->instances[] = $this->app->register($provider);
- }
- }
-
- /**
- * Get the services provided by the provider.
- *
- * @return array
- */
- public function provides()
- {
- $provides = [];
-
- foreach ($this->providers as $provider) {
- $instance = $this->app->resolveProvider($provider);
-
- $provides = array_merge($provides, $instance->provides());
- }
-
- return $provides;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use ArrayAccess;
-use InvalidArgumentException;
-use Illuminate\Support\Traits\Macroable;
-
-class Arr
-{
- use Macroable;
-
- /**
- * Determine whether the given value is array accessible.
- *
- * @param mixed $value
- * @return bool
- */
- public static function accessible($value)
- {
- return is_array($value) || $value instanceof ArrayAccess;
- }
-
- /**
- * Add an element to an array using "dot" notation if it doesn't exist.
- *
- * @param array $array
- * @param string $key
- * @param mixed $value
- * @return array
- */
- public static function add($array, $key, $value)
- {
- if (is_null(static::get($array, $key))) {
- static::set($array, $key, $value);
- }
-
- return $array;
- }
-
- /**
- * Collapse an array of arrays into a single array.
- *
- * @param array $array
- * @return array
- */
- public static function collapse($array)
- {
- $results = [];
-
- foreach ($array as $values) {
- if ($values instanceof Collection) {
- $values = $values->all();
- } elseif (! is_array($values)) {
- continue;
- }
-
- $results[] = $values;
- }
-
- return array_merge([], ...$results);
- }
-
- /**
- * Cross join the given arrays, returning all possible permutations.
- *
- * @param array ...$arrays
- * @return array
- */
- public static function crossJoin(...$arrays)
- {
- $results = [[]];
-
- foreach ($arrays as $index => $array) {
- $append = [];
-
- foreach ($results as $product) {
- foreach ($array as $item) {
- $product[$index] = $item;
-
- $append[] = $product;
- }
- }
-
- $results = $append;
- }
-
- return $results;
- }
-
- /**
- * Divide an array into two arrays. One with keys and the other with values.
- *
- * @param array $array
- * @return array
- */
- public static function divide($array)
- {
- return [array_keys($array), array_values($array)];
- }
-
- /**
- * Flatten a multi-dimensional associative array with dots.
- *
- * @param array $array
- * @param string $prepend
- * @return array
- */
- public static function dot($array, $prepend = '')
- {
- $results = [];
-
- foreach ($array as $key => $value) {
- if (is_array($value) && ! empty($value)) {
- $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
- } else {
- $results[$prepend.$key] = $value;
- }
- }
-
- return $results;
- }
-
- /**
- * Get all of the given array except for a specified array of keys.
- *
- * @param array $array
- * @param array|string $keys
- * @return array
- */
- public static function except($array, $keys)
- {
- static::forget($array, $keys);
-
- return $array;
- }
-
- /**
- * Determine if the given key exists in the provided array.
- *
- * @param \ArrayAccess|array $array
- * @param string|int $key
- * @return bool
- */
- public static function exists($array, $key)
- {
- if ($array instanceof ArrayAccess) {
- return $array->offsetExists($key);
- }
-
- return array_key_exists($key, $array);
- }
-
- /**
- * Return the first element in an array passing a given truth test.
- *
- * @param array $array
- * @param callable|null $callback
- * @param mixed $default
- * @return mixed
- */
- public static function first($array, callable $callback = null, $default = null)
- {
- if (is_null($callback)) {
- if (empty($array)) {
- return value($default);
- }
-
- foreach ($array as $item) {
- return $item;
- }
- }
-
- foreach ($array as $key => $value) {
- if (call_user_func($callback, $value, $key)) {
- return $value;
- }
- }
-
- return value($default);
- }
-
- /**
- * Return the last element in an array passing a given truth test.
- *
- * @param array $array
- * @param callable|null $callback
- * @param mixed $default
- * @return mixed
- */
- public static function last($array, callable $callback = null, $default = null)
- {
- if (is_null($callback)) {
- return empty($array) ? value($default) : end($array);
- }
-
- return static::first(array_reverse($array, true), $callback, $default);
- }
-
- /**
- * Flatten a multi-dimensional array into a single level.
- *
- * @param array $array
- * @param int $depth
- * @return array
- */
- public static function flatten($array, $depth = INF)
- {
- $result = [];
-
- foreach ($array as $item) {
- $item = $item instanceof Collection ? $item->all() : $item;
-
- if (! is_array($item)) {
- $result[] = $item;
- } else {
- $values = $depth === 1
- ? array_values($item)
- : static::flatten($item, $depth - 1);
-
- foreach ($values as $value) {
- $result[] = $value;
- }
- }
- }
-
- return $result;
- }
-
- /**
- * Remove one or many array items from a given array using "dot" notation.
- *
- * @param array $array
- * @param array|string $keys
- * @return void
- */
- public static function forget(&$array, $keys)
- {
- $original = &$array;
-
- $keys = (array) $keys;
-
- if (count($keys) === 0) {
- return;
- }
-
- foreach ($keys as $key) {
- // if the exact key exists in the top-level, remove it
- if (static::exists($array, $key)) {
- unset($array[$key]);
-
- continue;
- }
-
- $parts = explode('.', $key);
-
- // clean up before each pass
- $array = &$original;
-
- while (count($parts) > 1) {
- $part = array_shift($parts);
-
- if (isset($array[$part]) && is_array($array[$part])) {
- $array = &$array[$part];
- } else {
- continue 2;
- }
- }
-
- unset($array[array_shift($parts)]);
- }
- }
-
- /**
- * Get an item from an array using "dot" notation.
- *
- * @param \ArrayAccess|array $array
- * @param string|int $key
- * @param mixed $default
- * @return mixed
- */
- public static function get($array, $key, $default = null)
- {
- if (! static::accessible($array)) {
- return value($default);
- }
-
- if (is_null($key)) {
- return $array;
- }
-
- if (static::exists($array, $key)) {
- return $array[$key];
- }
-
- if (strpos($key, '.') === false) {
- return $array[$key] ?? value($default);
- }
-
- foreach (explode('.', $key) as $segment) {
- if (static::accessible($array) && static::exists($array, $segment)) {
- $array = $array[$segment];
- } else {
- return value($default);
- }
- }
-
- return $array;
- }
-
- /**
- * Check if an item or items exist in an array using "dot" notation.
- *
- * @param \ArrayAccess|array $array
- * @param string|array $keys
- * @return bool
- */
- public static function has($array, $keys)
- {
- $keys = (array) $keys;
-
- if (! $array || $keys === []) {
- return false;
- }
-
- foreach ($keys as $key) {
- $subKeyArray = $array;
-
- if (static::exists($array, $key)) {
- continue;
- }
-
- foreach (explode('.', $key) as $segment) {
- if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
- $subKeyArray = $subKeyArray[$segment];
- } else {
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Determines if an array is associative.
- *
- * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
- *
- * @param array $array
- * @return bool
- */
- public static function isAssoc(array $array)
- {
- $keys = array_keys($array);
-
- return array_keys($keys) !== $keys;
- }
-
- /**
- * Get a subset of the items from the given array.
- *
- * @param array $array
- * @param array|string $keys
- * @return array
- */
- public static function only($array, $keys)
- {
- return array_intersect_key($array, array_flip((array) $keys));
- }
-
- /**
- * Pluck an array of values from an array.
- *
- * @param array $array
- * @param string|array $value
- * @param string|array|null $key
- * @return array
- */
- public static function pluck($array, $value, $key = null)
- {
- $results = [];
-
- [$value, $key] = static::explodePluckParameters($value, $key);
-
- foreach ($array as $item) {
- $itemValue = data_get($item, $value);
-
- // If the key is "null", we will just append the value to the array and keep
- // looping. Otherwise we will key the array using the value of the key we
- // received from the developer. Then we'll return the final array form.
- if (is_null($key)) {
- $results[] = $itemValue;
- } else {
- $itemKey = data_get($item, $key);
-
- if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
- $itemKey = (string) $itemKey;
- }
-
- $results[$itemKey] = $itemValue;
- }
- }
-
- return $results;
- }
-
- /**
- * Explode the "value" and "key" arguments passed to "pluck".
- *
- * @param string|array $value
- * @param string|array|null $key
- * @return array
- */
- protected static function explodePluckParameters($value, $key)
- {
- $value = is_string($value) ? explode('.', $value) : $value;
-
- $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
-
- return [$value, $key];
- }
-
- /**
- * Push an item onto the beginning of an array.
- *
- * @param array $array
- * @param mixed $value
- * @param mixed $key
- * @return array
- */
- public static function prepend($array, $value, $key = null)
- {
- if (is_null($key)) {
- array_unshift($array, $value);
- } else {
- $array = [$key => $value] + $array;
- }
-
- return $array;
- }
-
- /**
- * Get a value from the array, and remove it.
- *
- * @param array $array
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- public static function pull(&$array, $key, $default = null)
- {
- $value = static::get($array, $key, $default);
-
- static::forget($array, $key);
-
- return $value;
- }
-
- /**
- * Get one or a specified number of random values from an array.
- *
- * @param array $array
- * @param int|null $number
- * @return mixed
- *
- * @throws \InvalidArgumentException
- */
- public static function random($array, $number = null)
- {
- $requested = is_null($number) ? 1 : $number;
-
- $count = count($array);
-
- if ($requested > $count) {
- throw new InvalidArgumentException(
- "You requested {$requested} items, but there are only {$count} items available."
- );
- }
-
- if (is_null($number)) {
- return $array[array_rand($array)];
- }
-
- if ((int) $number === 0) {
- return [];
- }
-
- $keys = array_rand($array, $number);
-
- $results = [];
-
- foreach ((array) $keys as $key) {
- $results[] = $array[$key];
- }
-
- return $results;
- }
-
- /**
- * Set an array item to a given value using "dot" notation.
- *
- * If no key is given to the method, the entire array will be replaced.
- *
- * @param array $array
- * @param string $key
- * @param mixed $value
- * @return array
- */
- public static function set(&$array, $key, $value)
- {
- if (is_null($key)) {
- return $array = $value;
- }
-
- $keys = explode('.', $key);
-
- while (count($keys) > 1) {
- $key = array_shift($keys);
-
- // If the key doesn't exist at this depth, we will just create an empty array
- // to hold the next value, allowing us to create the arrays to hold final
- // values at the correct depth. Then we'll keep digging into the array.
- if (! isset($array[$key]) || ! is_array($array[$key])) {
- $array[$key] = [];
- }
-
- $array = &$array[$key];
- }
-
- $array[array_shift($keys)] = $value;
-
- return $array;
- }
-
- /**
- * Shuffle the given array and return the result.
- *
- * @param array $array
- * @param int|null $seed
- * @return array
- */
- public static function shuffle($array, $seed = null)
- {
- if (is_null($seed)) {
- shuffle($array);
- } else {
- mt_srand($seed);
- shuffle($array);
- mt_srand();
- }
-
- return $array;
- }
-
- /**
- * Sort the array using the given callback or "dot" notation.
- *
- * @param array $array
- * @param callable|string|null $callback
- * @return array
- */
- public static function sort($array, $callback = null)
- {
- return Collection::make($array)->sortBy($callback)->all();
- }
-
- /**
- * Recursively sort an array by keys and values.
- *
- * @param array $array
- * @return array
- */
- public static function sortRecursive($array)
- {
- foreach ($array as &$value) {
- if (is_array($value)) {
- $value = static::sortRecursive($value);
- }
- }
-
- if (static::isAssoc($array)) {
- ksort($array);
- } else {
- sort($array);
- }
-
- return $array;
- }
-
- /**
- * Convert the array into a query string.
- *
- * @param array $array
- * @return string
- */
- public static function query($array)
- {
- return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
- }
-
- /**
- * Filter the array using the given callback.
- *
- * @param array $array
- * @param callable $callback
- * @return array
- */
- public static function where($array, callable $callback)
- {
- return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
- }
-
- /**
- * If the given value is not an array and not null, wrap it in one.
- *
- * @param mixed $value
- * @return array
- */
- public static function wrap($value)
- {
- if (is_null($value)) {
- return [];
- }
-
- return is_array($value) ? $value : [$value];
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Carbon\Carbon as BaseCarbon;
-
-class Carbon extends BaseCarbon
-{
- //
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use stdClass;
-use Countable;
-use Exception;
-use ArrayAccess;
-use Traversable;
-use ArrayIterator;
-use CachingIterator;
-use JsonSerializable;
-use IteratorAggregate;
-use Illuminate\Support\Traits\Macroable;
-use Illuminate\Contracts\Support\Jsonable;
-use Symfony\Component\VarDumper\VarDumper;
-use Illuminate\Contracts\Support\Arrayable;
-
-/**
- * @property-read HigherOrderCollectionProxy $average
- * @property-read HigherOrderCollectionProxy $avg
- * @property-read HigherOrderCollectionProxy $contains
- * @property-read HigherOrderCollectionProxy $each
- * @property-read HigherOrderCollectionProxy $every
- * @property-read HigherOrderCollectionProxy $filter
- * @property-read HigherOrderCollectionProxy $first
- * @property-read HigherOrderCollectionProxy $flatMap
- * @property-read HigherOrderCollectionProxy $groupBy
- * @property-read HigherOrderCollectionProxy $keyBy
- * @property-read HigherOrderCollectionProxy $map
- * @property-read HigherOrderCollectionProxy $max
- * @property-read HigherOrderCollectionProxy $min
- * @property-read HigherOrderCollectionProxy $partition
- * @property-read HigherOrderCollectionProxy $reject
- * @property-read HigherOrderCollectionProxy $sortBy
- * @property-read HigherOrderCollectionProxy $sortByDesc
- * @property-read HigherOrderCollectionProxy $sum
- * @property-read HigherOrderCollectionProxy $unique
- */
-class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
-{
- use Macroable;
-
- /**
- * The items contained in the collection.
- *
- * @var array
- */
- protected $items = [];
-
- /**
- * The methods that can be proxied.
- *
- * @var array
- */
- protected static $proxies = [
- 'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
- 'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
- 'reject', 'some', 'sortBy', 'sortByDesc', 'sum', 'unique',
- ];
-
- /**
- * Create a new collection.
- *
- * @param mixed $items
- * @return void
- */
- public function __construct($items = [])
- {
- $this->items = $this->getArrayableItems($items);
- }
-
- /**
- * Create a new collection instance if the value isn't one already.
- *
- * @param mixed $items
- * @return static
- */
- public static function make($items = [])
- {
- return new static($items);
- }
-
- /**
- * Wrap the given value in a collection if applicable.
- *
- * @param mixed $value
- * @return static
- */
- public static function wrap($value)
- {
- return $value instanceof self
- ? new static($value)
- : new static(Arr::wrap($value));
- }
-
- /**
- * Get the underlying items from the given collection if applicable.
- *
- * @param array|static $value
- * @return array
- */
- public static function unwrap($value)
- {
- return $value instanceof self ? $value->all() : $value;
- }
-
- /**
- * Create a new collection by invoking the callback a given amount of times.
- *
- * @param int $number
- * @param callable $callback
- * @return static
- */
- public static function times($number, callable $callback = null)
- {
- if ($number < 1) {
- return new static;
- }
-
- if (is_null($callback)) {
- return new static(range(1, $number));
- }
-
- return (new static(range(1, $number)))->map($callback);
- }
-
- /**
- * Get all of the items in the collection.
- *
- * @return array
- */
- public function all()
- {
- return $this->items;
- }
-
- /**
- * Get the average value of a given key.
- *
- * @param callable|string|null $callback
- * @return mixed
- */
- public function avg($callback = null)
- {
- $callback = $this->valueRetriever($callback);
-
- $items = $this->map(function ($value) use ($callback) {
- return $callback($value);
- })->filter(function ($value) {
- return ! is_null($value);
- });
-
- if ($count = $items->count()) {
- return $items->sum() / $count;
- }
- }
-
- /**
- * Alias for the "avg" method.
- *
- * @param callable|string|null $callback
- * @return mixed
- */
- public function average($callback = null)
- {
- return $this->avg($callback);
- }
-
- /**
- * Get the median of a given key.
- *
- * @param string|array|null $key
- * @return mixed
- */
- public function median($key = null)
- {
- $values = (isset($key) ? $this->pluck($key) : $this)
- ->filter(function ($item) {
- return ! is_null($item);
- })->sort()->values();
-
- $count = $values->count();
-
- if ($count === 0) {
- return;
- }
-
- $middle = (int) ($count / 2);
-
- if ($count % 2) {
- return $values->get($middle);
- }
-
- return (new static([
- $values->get($middle - 1), $values->get($middle),
- ]))->average();
- }
-
- /**
- * Get the mode of a given key.
- *
- * @param string|array|null $key
- * @return array|null
- */
- public function mode($key = null)
- {
- if ($this->count() === 0) {
- return;
- }
-
- $collection = isset($key) ? $this->pluck($key) : $this;
-
- $counts = new self;
-
- $collection->each(function ($value) use ($counts) {
- $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
- });
-
- $sorted = $counts->sort();
-
- $highestValue = $sorted->last();
-
- return $sorted->filter(function ($value) use ($highestValue) {
- return $value == $highestValue;
- })->sort()->keys()->all();
- }
-
- /**
- * Collapse the collection of items into a single array.
- *
- * @return static
- */
- public function collapse()
- {
- return new static(Arr::collapse($this->items));
- }
-
- /**
- * Alias for the "contains" method.
- *
- * @param mixed $key
- * @param mixed $operator
- * @param mixed $value
- * @return bool
- */
- public function some($key, $operator = null, $value = null)
- {
- return $this->contains(...func_get_args());
- }
-
- /**
- * Determine if an item exists in the collection.
- *
- * @param mixed $key
- * @param mixed $operator
- * @param mixed $value
- * @return bool
- */
- public function contains($key, $operator = null, $value = null)
- {
- if (func_num_args() === 1) {
- if ($this->useAsCallable($key)) {
- $placeholder = new stdClass;
-
- return $this->first($key, $placeholder) !== $placeholder;
- }
-
- return in_array($key, $this->items);
- }
-
- return $this->contains($this->operatorForWhere(...func_get_args()));
- }
-
- /**
- * Determine if an item exists in the collection using strict comparison.
- *
- * @param mixed $key
- * @param mixed $value
- * @return bool
- */
- public function containsStrict($key, $value = null)
- {
- if (func_num_args() === 2) {
- return $this->contains(function ($item) use ($key, $value) {
- return data_get($item, $key) === $value;
- });
- }
-
- if ($this->useAsCallable($key)) {
- return ! is_null($this->first($key));
- }
-
- return in_array($key, $this->items, true);
- }
-
- /**
- * Cross join with the given lists, returning all possible permutations.
- *
- * @param mixed ...$lists
- * @return static
- */
- public function crossJoin(...$lists)
- {
- return new static(Arr::crossJoin(
- $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
- ));
- }
-
- /**
- * Dump the collection and end the script.
- *
- * @param mixed ...$args
- * @return void
- */
- public function dd(...$args)
- {
- call_user_func_array([$this, 'dump'], $args);
-
- die(1);
- }
-
- /**
- * Dump the collection.
- *
- * @return $this
- */
- public function dump()
- {
- (new static(func_get_args()))
- ->push($this)
- ->each(function ($item) {
- VarDumper::dump($item);
- });
-
- return $this;
- }
-
- /**
- * Get the items in the collection that are not present in the given items.
- *
- * @param mixed $items
- * @return static
- */
- public function diff($items)
- {
- return new static(array_diff($this->items, $this->getArrayableItems($items)));
- }
-
- /**
- * Get the items in the collection that are not present in the given items.
- *
- * @param mixed $items
- * @param callable $callback
- * @return static
- */
- public function diffUsing($items, callable $callback)
- {
- return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
- }
-
- /**
- * Get the items in the collection whose keys and values are not present in the given items.
- *
- * @param mixed $items
- * @return static
- */
- public function diffAssoc($items)
- {
- return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
- }
-
- /**
- * Get the items in the collection whose keys and values are not present in the given items.
- *
- * @param mixed $items
- * @param callable $callback
- * @return static
- */
- public function diffAssocUsing($items, callable $callback)
- {
- return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
- }
-
- /**
- * Get the items in the collection whose keys are not present in the given items.
- *
- * @param mixed $items
- * @return static
- */
- public function diffKeys($items)
- {
- return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
- }
-
- /**
- * Get the items in the collection whose keys are not present in the given items.
- *
- * @param mixed $items
- * @param callable $callback
- * @return static
- */
- public function diffKeysUsing($items, callable $callback)
- {
- return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
- }
-
- /**
- * Retrieve duplicate items from the collection.
- *
- * @param callable|null $callback
- * @param bool $strict
- * @return static
- */
- public function duplicates($callback = null, $strict = false)
- {
- $items = $this->map($this->valueRetriever($callback));
-
- $uniqueItems = $items->unique(null, $strict);
-
- $compare = $this->duplicateComparator($strict);
-
- $duplicates = new static;
-
- foreach ($items as $key => $value) {
- if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {
- $uniqueItems->shift();
- } else {
- $duplicates[$key] = $value;
- }
- }
-
- return $duplicates;
- }
-
- /**
- * Retrieve duplicate items from the collection using strict comparison.
- *
- * @param callable|null $callback
- * @return static
- */
- public function duplicatesStrict($callback = null)
- {
- return $this->duplicates($callback, true);
- }
-
- /**
- * Get the comparison function to detect duplicates.
- *
- * @param bool $strict
- * @return \Closure
- */
- protected function duplicateComparator($strict)
- {
- if ($strict) {
- return function ($a, $b) {
- return $a === $b;
- };
- }
-
- return function ($a, $b) {
- return $a == $b;
- };
- }
-
- /**
- * Execute a callback over each item.
- *
- * @param callable $callback
- * @return $this
- */
- public function each(callable $callback)
- {
- foreach ($this->items as $key => $item) {
- if ($callback($item, $key) === false) {
- break;
- }
- }
-
- return $this;
- }
-
- /**
- * Execute a callback over each nested chunk of items.
- *
- * @param callable $callback
- * @return static
- */
- public function eachSpread(callable $callback)
- {
- return $this->each(function ($chunk, $key) use ($callback) {
- $chunk[] = $key;
-
- return $callback(...$chunk);
- });
- }
-
- /**
- * Determine if all items in the collection pass the given test.
- *
- * @param string|callable $key
- * @param mixed $operator
- * @param mixed $value
- * @return bool
- */
- public function every($key, $operator = null, $value = null)
- {
- if (func_num_args() === 1) {
- $callback = $this->valueRetriever($key);
-
- foreach ($this->items as $k => $v) {
- if (! $callback($v, $k)) {
- return false;
- }
- }
-
- return true;
- }
-
- return $this->every($this->operatorForWhere(...func_get_args()));
- }
-
- /**
- * Get all items except for those with the specified keys.
- *
- * @param \Illuminate\Support\Collection|mixed $keys
- * @return static
- */
- public function except($keys)
- {
- if ($keys instanceof self) {
- $keys = $keys->all();
- } elseif (! is_array($keys)) {
- $keys = func_get_args();
- }
-
- return new static(Arr::except($this->items, $keys));
- }
-
- /**
- * Run a filter over each of the items.
- *
- * @param callable|null $callback
- * @return static
- */
- public function filter(callable $callback = null)
- {
- if ($callback) {
- return new static(Arr::where($this->items, $callback));
- }
-
- return new static(array_filter($this->items));
- }
-
- /**
- * Apply the callback if the value is truthy.
- *
- * @param bool $value
- * @param callable $callback
- * @param callable $default
- * @return static|mixed
- */
- public function when($value, callable $callback, callable $default = null)
- {
- if ($value) {
- return $callback($this, $value);
- } elseif ($default) {
- return $default($this, $value);
- }
-
- return $this;
- }
-
- /**
- * Apply the callback if the collection is empty.
- *
- * @param callable $callback
- * @param callable $default
- * @return static|mixed
- */
- public function whenEmpty(callable $callback, callable $default = null)
- {
- return $this->when($this->isEmpty(), $callback, $default);
- }
-
- /**
- * Apply the callback if the collection is not empty.
- *
- * @param callable $callback
- * @param callable $default
- * @return static|mixed
- */
- public function whenNotEmpty(callable $callback, callable $default = null)
- {
- return $this->when($this->isNotEmpty(), $callback, $default);
- }
-
- /**
- * Apply the callback if the value is falsy.
- *
- * @param bool $value
- * @param callable $callback
- * @param callable $default
- * @return static|mixed
- */
- public function unless($value, callable $callback, callable $default = null)
- {
- return $this->when(! $value, $callback, $default);
- }
-
- /**
- * Apply the callback unless the collection is empty.
- *
- * @param callable $callback
- * @param callable $default
- * @return static|mixed
- */
- public function unlessEmpty(callable $callback, callable $default = null)
- {
- return $this->whenNotEmpty($callback, $default);
- }
-
- /**
- * Apply the callback unless the collection is not empty.
- *
- * @param callable $callback
- * @param callable $default
- * @return static|mixed
- */
- public function unlessNotEmpty(callable $callback, callable $default = null)
- {
- return $this->whenEmpty($callback, $default);
- }
-
- /**
- * Filter items by the given key value pair.
- *
- * @param string $key
- * @param mixed $operator
- * @param mixed $value
- * @return static
- */
- public function where($key, $operator = null, $value = null)
- {
- return $this->filter($this->operatorForWhere(...func_get_args()));
- }
-
- /**
- * Get an operator checker callback.
- *
- * @param string $key
- * @param string $operator
- * @param mixed $value
- * @return \Closure
- */
- protected function operatorForWhere($key, $operator = null, $value = null)
- {
- if (func_num_args() === 1) {
- $value = true;
-
- $operator = '=';
- }
-
- if (func_num_args() === 2) {
- $value = $operator;
-
- $operator = '=';
- }
-
- return function ($item) use ($key, $operator, $value) {
- $retrieved = data_get($item, $key);
-
- $strings = array_filter([$retrieved, $value], function ($value) {
- return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
- });
-
- if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
- return in_array($operator, ['!=', '<>', '!==']);
- }
-
- switch ($operator) {
- default:
- case '=':
- case '==': return $retrieved == $value;
- case '!=':
- case '<>': return $retrieved != $value;
- case '<': return $retrieved < $value;
- case '>': return $retrieved > $value;
- case '<=': return $retrieved <= $value;
- case '>=': return $retrieved >= $value;
- case '===': return $retrieved === $value;
- case '!==': return $retrieved !== $value;
- }
- };
- }
-
- /**
- * Filter items by the given key value pair using strict comparison.
- *
- * @param string $key
- * @param mixed $value
- * @return static
- */
- public function whereStrict($key, $value)
- {
- return $this->where($key, '===', $value);
- }
-
- /**
- * Filter items by the given key value pair.
- *
- * @param string $key
- * @param mixed $values
- * @param bool $strict
- * @return static
- */
- public function whereIn($key, $values, $strict = false)
- {
- $values = $this->getArrayableItems($values);
-
- return $this->filter(function ($item) use ($key, $values, $strict) {
- return in_array(data_get($item, $key), $values, $strict);
- });
- }
-
- /**
- * Filter items by the given key value pair using strict comparison.
- *
- * @param string $key
- * @param mixed $values
- * @return static
- */
- public function whereInStrict($key, $values)
- {
- return $this->whereIn($key, $values, true);
- }
-
- /**
- * Filter items such that the value of the given key is between the given values.
- *
- * @param string $key
- * @param array $values
- * @return static
- */
- public function whereBetween($key, $values)
- {
- return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
- }
-
- /**
- * Filter items such that the value of the given key is not between the given values.
- *
- * @param string $key
- * @param array $values
- * @return static
- */
- public function whereNotBetween($key, $values)
- {
- return $this->filter(function ($item) use ($key, $values) {
- return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);
- });
- }
-
- /**
- * Filter items by the given key value pair.
- *
- * @param string $key
- * @param mixed $values
- * @param bool $strict
- * @return static
- */
- public function whereNotIn($key, $values, $strict = false)
- {
- $values = $this->getArrayableItems($values);
-
- return $this->reject(function ($item) use ($key, $values, $strict) {
- return in_array(data_get($item, $key), $values, $strict);
- });
- }
-
- /**
- * Filter items by the given key value pair using strict comparison.
- *
- * @param string $key
- * @param mixed $values
- * @return static
- */
- public function whereNotInStrict($key, $values)
- {
- return $this->whereNotIn($key, $values, true);
- }
-
- /**
- * Filter the items, removing any items that don't match the given type.
- *
- * @param string $type
- * @return static
- */
- public function whereInstanceOf($type)
- {
- return $this->filter(function ($value) use ($type) {
- return $value instanceof $type;
- });
- }
-
- /**
- * Get the first item from the collection passing the given truth test.
- *
- * @param callable|null $callback
- * @param mixed $default
- * @return mixed
- */
- public function first(callable $callback = null, $default = null)
- {
- return Arr::first($this->items, $callback, $default);
- }
-
- /**
- * Get the first item by the given key value pair.
- *
- * @param string $key
- * @param mixed $operator
- * @param mixed $value
- * @return mixed
- */
- public function firstWhere($key, $operator = null, $value = null)
- {
- return $this->first($this->operatorForWhere(...func_get_args()));
- }
-
- /**
- * Get a flattened array of the items in the collection.
- *
- * @param int $depth
- * @return static
- */
- public function flatten($depth = INF)
- {
- return new static(Arr::flatten($this->items, $depth));
- }
-
- /**
- * Flip the items in the collection.
- *
- * @return static
- */
- public function flip()
- {
- return new static(array_flip($this->items));
- }
-
- /**
- * Remove an item from the collection by key.
- *
- * @param string|array $keys
- * @return $this
- */
- public function forget($keys)
- {
- foreach ((array) $keys as $key) {
- $this->offsetUnset($key);
- }
-
- return $this;
- }
-
- /**
- * Get an item from the collection by key.
- *
- * @param mixed $key
- * @param mixed $default
- * @return mixed
- */
- public function get($key, $default = null)
- {
- if ($this->offsetExists($key)) {
- return $this->items[$key];
- }
-
- return value($default);
- }
-
- /**
- * Group an associative array by a field or using a callback.
- *
- * @param array|callable|string $groupBy
- * @param bool $preserveKeys
- * @return static
- */
- public function groupBy($groupBy, $preserveKeys = false)
- {
- if (is_array($groupBy)) {
- $nextGroups = $groupBy;
-
- $groupBy = array_shift($nextGroups);
- }
-
- $groupBy = $this->valueRetriever($groupBy);
-
- $results = [];
-
- foreach ($this->items as $key => $value) {
- $groupKeys = $groupBy($value, $key);
-
- if (! is_array($groupKeys)) {
- $groupKeys = [$groupKeys];
- }
-
- foreach ($groupKeys as $groupKey) {
- $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
-
- if (! array_key_exists($groupKey, $results)) {
- $results[$groupKey] = new static;
- }
-
- $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
- }
- }
-
- $result = new static($results);
-
- if (! empty($nextGroups)) {
- return $result->map->groupBy($nextGroups, $preserveKeys);
- }
-
- return $result;
- }
-
- /**
- * Key an associative array by a field or using a callback.
- *
- * @param callable|string $keyBy
- * @return static
- */
- public function keyBy($keyBy)
- {
- $keyBy = $this->valueRetriever($keyBy);
-
- $results = [];
-
- foreach ($this->items as $key => $item) {
- $resolvedKey = $keyBy($item, $key);
-
- if (is_object($resolvedKey)) {
- $resolvedKey = (string) $resolvedKey;
- }
-
- $results[$resolvedKey] = $item;
- }
-
- return new static($results);
- }
-
- /**
- * Determine if an item exists in the collection by key.
- *
- * @param mixed $key
- * @return bool
- */
- public function has($key)
- {
- $keys = is_array($key) ? $key : func_get_args();
-
- foreach ($keys as $value) {
- if (! $this->offsetExists($value)) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Concatenate values of a given key as a string.
- *
- * @param string $value
- * @param string $glue
- * @return string
- */
- public function implode($value, $glue = null)
- {
- $first = $this->first();
-
- if (is_array($first) || is_object($first)) {
- return implode($glue, $this->pluck($value)->all());
- }
-
- return implode($value, $this->items);
- }
-
- /**
- * Intersect the collection with the given items.
- *
- * @param mixed $items
- * @return static
- */
- public function intersect($items)
- {
- return new static(array_intersect($this->items, $this->getArrayableItems($items)));
- }
-
- /**
- * Intersect the collection with the given items by key.
- *
- * @param mixed $items
- * @return static
- */
- public function intersectByKeys($items)
- {
- return new static(array_intersect_key(
- $this->items, $this->getArrayableItems($items)
- ));
- }
-
- /**
- * Determine if the collection is empty or not.
- *
- * @return bool
- */
- public function isEmpty()
- {
- return empty($this->items);
- }
-
- /**
- * Determine if the collection is not empty.
- *
- * @return bool
- */
- public function isNotEmpty()
- {
- return ! $this->isEmpty();
- }
-
- /**
- * Determine if the given value is callable, but not a string.
- *
- * @param mixed $value
- * @return bool
- */
- protected function useAsCallable($value)
- {
- return ! is_string($value) && is_callable($value);
- }
-
- /**
- * Join all items from the collection using a string. The final items can use a separate glue string.
- *
- * @param string $glue
- * @param string $finalGlue
- * @return string
- */
- public function join($glue, $finalGlue = '')
- {
- if ($finalGlue === '') {
- return $this->implode($glue);
- }
-
- $count = $this->count();
-
- if ($count === 0) {
- return '';
- }
-
- if ($count === 1) {
- return $this->last();
- }
-
- $collection = new static($this->items);
-
- $finalItem = $collection->pop();
-
- return $collection->implode($glue).$finalGlue.$finalItem;
- }
-
- /**
- * Get the keys of the collection items.
- *
- * @return static
- */
- public function keys()
- {
- return new static(array_keys($this->items));
- }
-
- /**
- * Get the last item from the collection.
- *
- * @param callable|null $callback
- * @param mixed $default
- * @return mixed
- */
- public function last(callable $callback = null, $default = null)
- {
- return Arr::last($this->items, $callback, $default);
- }
-
- /**
- * Get the values of a given key.
- *
- * @param string|array $value
- * @param string|null $key
- * @return static
- */
- public function pluck($value, $key = null)
- {
- return new static(Arr::pluck($this->items, $value, $key));
- }
-
- /**
- * Run a map over each of the items.
- *
- * @param callable $callback
- * @return static
- */
- public function map(callable $callback)
- {
- $keys = array_keys($this->items);
-
- $items = array_map($callback, $this->items, $keys);
-
- return new static(array_combine($keys, $items));
- }
-
- /**
- * Run a map over each nested chunk of items.
- *
- * @param callable $callback
- * @return static
- */
- public function mapSpread(callable $callback)
- {
- return $this->map(function ($chunk, $key) use ($callback) {
- $chunk[] = $key;
-
- return $callback(...$chunk);
- });
- }
-
- /**
- * Run a dictionary map over the items.
- *
- * The callback should return an associative array with a single key/value pair.
- *
- * @param callable $callback
- * @return static
- */
- public function mapToDictionary(callable $callback)
- {
- $dictionary = [];
-
- foreach ($this->items as $key => $item) {
- $pair = $callback($item, $key);
-
- $key = key($pair);
-
- $value = reset($pair);
-
- if (! isset($dictionary[$key])) {
- $dictionary[$key] = [];
- }
-
- $dictionary[$key][] = $value;
- }
-
- return new static($dictionary);
- }
-
- /**
- * Run a grouping map over the items.
- *
- * The callback should return an associative array with a single key/value pair.
- *
- * @param callable $callback
- * @return static
- */
- public function mapToGroups(callable $callback)
- {
- $groups = $this->mapToDictionary($callback);
-
- return $groups->map([$this, 'make']);
- }
-
- /**
- * Run an associative map over each of the items.
- *
- * The callback should return an associative array with a single key/value pair.
- *
- * @param callable $callback
- * @return static
- */
- public function mapWithKeys(callable $callback)
- {
- $result = [];
-
- foreach ($this->items as $key => $value) {
- $assoc = $callback($value, $key);
-
- foreach ($assoc as $mapKey => $mapValue) {
- $result[$mapKey] = $mapValue;
- }
- }
-
- return new static($result);
- }
-
- /**
- * Map a collection and flatten the result by a single level.
- *
- * @param callable $callback
- * @return static
- */
- public function flatMap(callable $callback)
- {
- return $this->map($callback)->collapse();
- }
-
- /**
- * Map the values into a new class.
- *
- * @param string $class
- * @return static
- */
- public function mapInto($class)
- {
- return $this->map(function ($value, $key) use ($class) {
- return new $class($value, $key);
- });
- }
-
- /**
- * Get the max value of a given key.
- *
- * @param callable|string|null $callback
- * @return mixed
- */
- public function max($callback = null)
- {
- $callback = $this->valueRetriever($callback);
-
- return $this->filter(function ($value) {
- return ! is_null($value);
- })->reduce(function ($result, $item) use ($callback) {
- $value = $callback($item);
-
- return is_null($result) || $value > $result ? $value : $result;
- });
- }
-
- /**
- * Merge the collection with the given items.
- *
- * @param mixed $items
- * @return static
- */
- public function merge($items)
- {
- return new static(array_merge($this->items, $this->getArrayableItems($items)));
- }
-
- /**
- * Create a collection by using this collection for keys and another for its values.
- *
- * @param mixed $values
- * @return static
- */
- public function combine($values)
- {
- return new static(array_combine($this->all(), $this->getArrayableItems($values)));
- }
-
- /**
- * Union the collection with the given items.
- *
- * @param mixed $items
- * @return static
- */
- public function union($items)
- {
- return new static($this->items + $this->getArrayableItems($items));
- }
-
- /**
- * Get the min value of a given key.
- *
- * @param callable|string|null $callback
- * @return mixed
- */
- public function min($callback = null)
- {
- $callback = $this->valueRetriever($callback);
-
- return $this->map(function ($value) use ($callback) {
- return $callback($value);
- })->filter(function ($value) {
- return ! is_null($value);
- })->reduce(function ($result, $value) {
- return is_null($result) || $value < $result ? $value : $result;
- });
- }
-
- /**
- * Create a new collection consisting of every n-th element.
- *
- * @param int $step
- * @param int $offset
- * @return static
- */
- public function nth($step, $offset = 0)
- {
- $new = [];
-
- $position = 0;
-
- foreach ($this->items as $item) {
- if ($position % $step === $offset) {
- $new[] = $item;
- }
-
- $position++;
- }
-
- return new static($new);
- }
-
- /**
- * Get the items with the specified keys.
- *
- * @param mixed $keys
- * @return static
- */
- public function only($keys)
- {
- if (is_null($keys)) {
- return new static($this->items);
- }
-
- if ($keys instanceof self) {
- $keys = $keys->all();
- }
-
- $keys = is_array($keys) ? $keys : func_get_args();
-
- return new static(Arr::only($this->items, $keys));
- }
-
- /**
- * "Paginate" the collection by slicing it into a smaller collection.
- *
- * @param int $page
- * @param int $perPage
- * @return static
- */
- public function forPage($page, $perPage)
- {
- $offset = max(0, ($page - 1) * $perPage);
-
- return $this->slice($offset, $perPage);
- }
-
- /**
- * Partition the collection into two arrays using the given callback or key.
- *
- * @param callable|string $key
- * @param mixed $operator
- * @param mixed $value
- * @return static
- */
- public function partition($key, $operator = null, $value = null)
- {
- $partitions = [new static, new static];
-
- $callback = func_num_args() === 1
- ? $this->valueRetriever($key)
- : $this->operatorForWhere(...func_get_args());
-
- foreach ($this->items as $key => $item) {
- $partitions[(int) ! $callback($item, $key)][$key] = $item;
- }
-
- return new static($partitions);
- }
-
- /**
- * Pass the collection to the given callback and return the result.
- *
- * @param callable $callback
- * @return mixed
- */
- public function pipe(callable $callback)
- {
- return $callback($this);
- }
-
- /**
- * Get and remove the last item from the collection.
- *
- * @return mixed
- */
- public function pop()
- {
- return array_pop($this->items);
- }
-
- /**
- * Push an item onto the beginning of the collection.
- *
- * @param mixed $value
- * @param mixed $key
- * @return $this
- */
- public function prepend($value, $key = null)
- {
- $this->items = Arr::prepend($this->items, $value, $key);
-
- return $this;
- }
-
- /**
- * Push an item onto the end of the collection.
- *
- * @param mixed $value
- * @return $this
- */
- public function push($value)
- {
- $this->offsetSet(null, $value);
-
- return $this;
- }
-
- /**
- * Push all of the given items onto the collection.
- *
- * @param iterable $source
- * @return static
- */
- public function concat($source)
- {
- $result = new static($this);
-
- foreach ($source as $item) {
- $result->push($item);
- }
-
- return $result;
- }
-
- /**
- * Get and remove an item from the collection.
- *
- * @param mixed $key
- * @param mixed $default
- * @return mixed
- */
- public function pull($key, $default = null)
- {
- return Arr::pull($this->items, $key, $default);
- }
-
- /**
- * Put an item in the collection by key.
- *
- * @param mixed $key
- * @param mixed $value
- * @return $this
- */
- public function put($key, $value)
- {
- $this->offsetSet($key, $value);
-
- return $this;
- }
-
- /**
- * Get one or a specified number of items randomly from the collection.
- *
- * @param int|null $number
- * @return static|mixed
- *
- * @throws \InvalidArgumentException
- */
- public function random($number = null)
- {
- if (is_null($number)) {
- return Arr::random($this->items);
- }
-
- return new static(Arr::random($this->items, $number));
- }
-
- /**
- * Reduce the collection to a single value.
- *
- * @param callable $callback
- * @param mixed $initial
- * @return mixed
- */
- public function reduce(callable $callback, $initial = null)
- {
- return array_reduce($this->items, $callback, $initial);
- }
-
- /**
- * Create a collection of all elements that do not pass a given truth test.
- *
- * @param callable|mixed $callback
- * @return static
- */
- public function reject($callback = true)
- {
- $useAsCallable = $this->useAsCallable($callback);
-
- return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
- return $useAsCallable
- ? ! $callback($value, $key)
- : $value != $callback;
- });
- }
-
- /**
- * Reverse items order.
- *
- * @return static
- */
- public function reverse()
- {
- return new static(array_reverse($this->items, true));
- }
-
- /**
- * Search the collection for a given value and return the corresponding key if successful.
- *
- * @param mixed $value
- * @param bool $strict
- * @return mixed
- */
- public function search($value, $strict = false)
- {
- if (! $this->useAsCallable($value)) {
- return array_search($value, $this->items, $strict);
- }
-
- foreach ($this->items as $key => $item) {
- if (call_user_func($value, $item, $key)) {
- return $key;
- }
- }
-
- return false;
- }
-
- /**
- * Get and remove the first item from the collection.
- *
- * @return mixed
- */
- public function shift()
- {
- return array_shift($this->items);
- }
-
- /**
- * Shuffle the items in the collection.
- *
- * @param int $seed
- * @return static
- */
- public function shuffle($seed = null)
- {
- return new static(Arr::shuffle($this->items, $seed));
- }
-
- /**
- * Slice the underlying collection array.
- *
- * @param int $offset
- * @param int $length
- * @return static
- */
- public function slice($offset, $length = null)
- {
- return new static(array_slice($this->items, $offset, $length, true));
- }
-
- /**
- * Split a collection into a certain number of groups.
- *
- * @param int $numberOfGroups
- * @return static
- */
- public function split($numberOfGroups)
- {
- if ($this->isEmpty()) {
- return new static;
- }
-
- $groups = new static;
-
- $groupSize = floor($this->count() / $numberOfGroups);
-
- $remain = $this->count() % $numberOfGroups;
-
- $start = 0;
-
- for ($i = 0; $i < $numberOfGroups; $i++) {
- $size = $groupSize;
-
- if ($i < $remain) {
- $size++;
- }
-
- if ($size) {
- $groups->push(new static(array_slice($this->items, $start, $size)));
-
- $start += $size;
- }
- }
-
- return $groups;
- }
-
- /**
- * Chunk the underlying collection array.
- *
- * @param int $size
- * @return static
- */
- public function chunk($size)
- {
- if ($size <= 0) {
- return new static;
- }
-
- $chunks = [];
-
- foreach (array_chunk($this->items, $size, true) as $chunk) {
- $chunks[] = new static($chunk);
- }
-
- return new static($chunks);
- }
-
- /**
- * Sort through each item with a callback.
- *
- * @param callable|null $callback
- * @return static
- */
- public function sort(callable $callback = null)
- {
- $items = $this->items;
-
- $callback
- ? uasort($items, $callback)
- : asort($items);
-
- return new static($items);
- }
-
- /**
- * Sort the collection using the given callback.
- *
- * @param callable|string $callback
- * @param int $options
- * @param bool $descending
- * @return static
- */
- public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
- {
- $results = [];
-
- $callback = $this->valueRetriever($callback);
-
- // First we will loop through the items and get the comparator from a callback
- // function which we were given. Then, we will sort the returned values and
- // and grab the corresponding values for the sorted keys from this array.
- foreach ($this->items as $key => $value) {
- $results[$key] = $callback($value, $key);
- }
-
- $descending ? arsort($results, $options)
- : asort($results, $options);
-
- // Once we have sorted all of the keys in the array, we will loop through them
- // and grab the corresponding model so we can set the underlying items list
- // to the sorted version. Then we'll just return the collection instance.
- foreach (array_keys($results) as $key) {
- $results[$key] = $this->items[$key];
- }
-
- return new static($results);
- }
-
- /**
- * Sort the collection in descending order using the given callback.
- *
- * @param callable|string $callback
- * @param int $options
- * @return static
- */
- public function sortByDesc($callback, $options = SORT_REGULAR)
- {
- return $this->sortBy($callback, $options, true);
- }
-
- /**
- * Sort the collection keys.
- *
- * @param int $options
- * @param bool $descending
- * @return static
- */
- public function sortKeys($options = SORT_REGULAR, $descending = false)
- {
- $items = $this->items;
-
- $descending ? krsort($items, $options) : ksort($items, $options);
-
- return new static($items);
- }
-
- /**
- * Sort the collection keys in descending order.
- *
- * @param int $options
- * @return static
- */
- public function sortKeysDesc($options = SORT_REGULAR)
- {
- return $this->sortKeys($options, true);
- }
-
- /**
- * Splice a portion of the underlying collection array.
- *
- * @param int $offset
- * @param int|null $length
- * @param mixed $replacement
- * @return static
- */
- public function splice($offset, $length = null, $replacement = [])
- {
- if (func_num_args() === 1) {
- return new static(array_splice($this->items, $offset));
- }
-
- return new static(array_splice($this->items, $offset, $length, $replacement));
- }
-
- /**
- * Get the sum of the given values.
- *
- * @param callable|string|null $callback
- * @return mixed
- */
- public function sum($callback = null)
- {
- if (is_null($callback)) {
- return array_sum($this->items);
- }
-
- $callback = $this->valueRetriever($callback);
-
- return $this->reduce(function ($result, $item) use ($callback) {
- return $result + $callback($item);
- }, 0);
- }
-
- /**
- * Take the first or last {$limit} items.
- *
- * @param int $limit
- * @return static
- */
- public function take($limit)
- {
- if ($limit < 0) {
- return $this->slice($limit, abs($limit));
- }
-
- return $this->slice(0, $limit);
- }
-
- /**
- * Pass the collection to the given callback and then return it.
- *
- * @param callable $callback
- * @return $this
- */
- public function tap(callable $callback)
- {
- $callback(new static($this->items));
-
- return $this;
- }
-
- /**
- * Transform each item in the collection using a callback.
- *
- * @param callable $callback
- * @return $this
- */
- public function transform(callable $callback)
- {
- $this->items = $this->map($callback)->all();
-
- return $this;
- }
-
- /**
- * Return only unique items from the collection array.
- *
- * @param string|callable|null $key
- * @param bool $strict
- * @return static
- */
- public function unique($key = null, $strict = false)
- {
- $callback = $this->valueRetriever($key);
-
- $exists = [];
-
- return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
- if (in_array($id = $callback($item, $key), $exists, $strict)) {
- return true;
- }
-
- $exists[] = $id;
- });
- }
-
- /**
- * Return only unique items from the collection array using strict comparison.
- *
- * @param string|callable|null $key
- * @return static
- */
- public function uniqueStrict($key = null)
- {
- return $this->unique($key, true);
- }
-
- /**
- * Reset the keys on the underlying array.
- *
- * @return static
- */
- public function values()
- {
- return new static(array_values($this->items));
- }
-
- /**
- * Get a value retrieving callback.
- *
- * @param callable|string|null $value
- * @return callable
- */
- protected function valueRetriever($value)
- {
- if ($this->useAsCallable($value)) {
- return $value;
- }
-
- return function ($item) use ($value) {
- return data_get($item, $value);
- };
- }
-
- /**
- * Zip the collection together with one or more arrays.
- *
- * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
- * => [[1, 4], [2, 5], [3, 6]]
- *
- * @param mixed ...$items
- * @return static
- */
- public function zip($items)
- {
- $arrayableItems = array_map(function ($items) {
- return $this->getArrayableItems($items);
- }, func_get_args());
-
- $params = array_merge([function () {
- return new static(func_get_args());
- }, $this->items], $arrayableItems);
-
- return new static(call_user_func_array('array_map', $params));
- }
-
- /**
- * Pad collection to the specified length with a value.
- *
- * @param int $size
- * @param mixed $value
- * @return static
- */
- public function pad($size, $value)
- {
- return new static(array_pad($this->items, $size, $value));
- }
-
- /**
- * Get the collection of items as a plain array.
- *
- * @return array
- */
- public function toArray()
- {
- return array_map(function ($value) {
- return $value instanceof Arrayable ? $value->toArray() : $value;
- }, $this->items);
- }
-
- /**
- * Convert the object into something JSON serializable.
- *
- * @return array
- */
- public function jsonSerialize()
- {
- return array_map(function ($value) {
- if ($value instanceof JsonSerializable) {
- return $value->jsonSerialize();
- } elseif ($value instanceof Jsonable) {
- return json_decode($value->toJson(), true);
- } elseif ($value instanceof Arrayable) {
- return $value->toArray();
- }
-
- return $value;
- }, $this->items);
- }
-
- /**
- * Get the collection of items as JSON.
- *
- * @param int $options
- * @return string
- */
- public function toJson($options = 0)
- {
- return json_encode($this->jsonSerialize(), $options);
- }
-
- /**
- * Get an iterator for the items.
- *
- * @return \ArrayIterator
- */
- public function getIterator()
- {
- return new ArrayIterator($this->items);
- }
-
- /**
- * Get a CachingIterator instance.
- *
- * @param int $flags
- * @return \CachingIterator
- */
- public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
- {
- return new CachingIterator($this->getIterator(), $flags);
- }
-
- /**
- * Count the number of items in the collection.
- *
- * @return int
- */
- public function count()
- {
- return count($this->items);
- }
-
- /**
- * Count the number of items in the collection using a given truth test.
- *
- * @param callable|null $callback
- * @return static
- */
- public function countBy($callback = null)
- {
- if (is_null($callback)) {
- $callback = function ($value) {
- return $value;
- };
- }
-
- return new static($this->groupBy($callback)->map(function ($value) {
- return $value->count();
- }));
- }
-
- /**
- * Add an item to the collection.
- *
- * @param mixed $item
- * @return $this
- */
- public function add($item)
- {
- $this->items[] = $item;
-
- return $this;
- }
-
- /**
- * Get a base Support collection instance from this collection.
- *
- * @return \Illuminate\Support\Collection
- */
- public function toBase()
- {
- return new self($this);
- }
-
- /**
- * Determine if an item exists at an offset.
- *
- * @param mixed $key
- * @return bool
- */
- public function offsetExists($key)
- {
- return array_key_exists($key, $this->items);
- }
-
- /**
- * Get an item at a given offset.
- *
- * @param mixed $key
- * @return mixed
- */
- public function offsetGet($key)
- {
- return $this->items[$key];
- }
-
- /**
- * Set the item at a given offset.
- *
- * @param mixed $key
- * @param mixed $value
- * @return void
- */
- public function offsetSet($key, $value)
- {
- if (is_null($key)) {
- $this->items[] = $value;
- } else {
- $this->items[$key] = $value;
- }
- }
-
- /**
- * Unset the item at a given offset.
- *
- * @param string $key
- * @return void
- */
- public function offsetUnset($key)
- {
- unset($this->items[$key]);
- }
-
- /**
- * Convert the collection to its string representation.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->toJson();
- }
-
- /**
- * Results array of items from Collection or Arrayable.
- *
- * @param mixed $items
- * @return array
- */
- protected function getArrayableItems($items)
- {
- if (is_array($items)) {
- return $items;
- } elseif ($items instanceof self) {
- return $items->all();
- } elseif ($items instanceof Arrayable) {
- return $items->toArray();
- } elseif ($items instanceof Jsonable) {
- return json_decode($items->toJson(), true);
- } elseif ($items instanceof JsonSerializable) {
- return $items->jsonSerialize();
- } elseif ($items instanceof Traversable) {
- return iterator_to_array($items);
- }
-
- return (array) $items;
- }
-
- /**
- * Add a method to the list of proxied methods.
- *
- * @param string $method
- * @return void
- */
- public static function proxy($method)
- {
- static::$proxies[] = $method;
- }
-
- /**
- * Dynamically access collection proxies.
- *
- * @param string $key
- * @return mixed
- *
- * @throws \Exception
- */
- public function __get($key)
- {
- if (! in_array($key, static::$proxies)) {
- throw new Exception("Property [{$key}] does not exist on this collection instance.");
- }
-
- return new HigherOrderCollectionProxy($this, $key);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Illuminate\Filesystem\Filesystem;
-use Symfony\Component\Process\Process;
-use Symfony\Component\Process\PhpExecutableFinder;
-
-class Composer
-{
- /**
- * The filesystem instance.
- *
- * @var \Illuminate\Filesystem\Filesystem
- */
- protected $files;
-
- /**
- * The working path to regenerate from.
- *
- * @var string|null
- */
- protected $workingPath;
-
- /**
- * Create a new Composer manager instance.
- *
- * @param \Illuminate\Filesystem\Filesystem $files
- * @param string|null $workingPath
- * @return void
- */
- public function __construct(Filesystem $files, $workingPath = null)
- {
- $this->files = $files;
- $this->workingPath = $workingPath;
- }
-
- /**
- * Regenerate the Composer autoloader files.
- *
- * @param string|array $extra
- * @return void
- */
- public function dumpAutoloads($extra = '')
- {
- $extra = $extra ? (array) $extra : [];
-
- $command = array_merge($this->findComposer(), ['dump-autoload'], $extra);
-
- $this->getProcess($command)->run();
- }
-
- /**
- * Regenerate the optimized Composer autoloader files.
- *
- * @return void
- */
- public function dumpOptimized()
- {
- $this->dumpAutoloads('--optimize');
- }
-
- /**
- * Get the composer command for the environment.
- *
- * @return array
- */
- protected function findComposer()
- {
- if ($this->files->exists($this->workingPath.'/composer.phar')) {
- return [$this->phpBinary(), 'composer.phar'];
- }
-
- return ['composer'];
- }
-
- /**
- * Get the PHP binary.
- *
- * @return string
- */
- protected function phpBinary()
- {
- return ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));
- }
-
- /**
- * Get a new Symfony process instance.
- *
- * @param array $command
- * @return \Symfony\Component\Process\Process
- */
- protected function getProcess(array $command)
- {
- return (new Process($command, $this->workingPath))->setTimeout(null);
- }
-
- /**
- * Set the working path used by the class.
- *
- * @param string $path
- * @return $this
- */
- public function setWorkingPath($path)
- {
- $this->workingPath = realpath($path);
-
- return $this;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use InvalidArgumentException;
-
-class ConfigurationUrlParser
-{
- /**
- * The drivers aliases map.
- *
- * @var array
- */
- protected static $driverAliases = [
- 'mssql' => 'sqlsrv',
- 'mysql2' => 'mysql', // RDS
- 'postgres' => 'pgsql',
- 'postgresql' => 'pgsql',
- 'sqlite3' => 'sqlite',
- ];
-
- /**
- * Parse the database configuration, hydrating options using a database configuration URL if possible.
- *
- * @param array|string $config
- * @return array
- */
- public function parseConfiguration($config)
- {
- if (is_string($config)) {
- $config = ['url' => $config];
- }
-
- $url = $config['url'] ?? null;
-
- $config = Arr::except($config, 'url');
-
- if (! $url) {
- return $config;
- }
-
- $parsedUrl = $this->parseUrl($url);
-
- return array_merge(
- $config,
- $this->getPrimaryOptions($parsedUrl),
- $this->getQueryOptions($parsedUrl)
- );
- }
-
- /**
- * Get the primary database connection options.
- *
- * @param array $url
- * @return array
- */
- protected function getPrimaryOptions($url)
- {
- return array_filter([
- 'driver' => $this->getDriver($url),
- 'database' => $this->getDatabase($url),
- 'host' => $url['host'] ?? null,
- 'port' => $url['port'] ?? null,
- 'username' => $url['user'] ?? null,
- 'password' => $url['pass'] ?? null,
- ], function ($value) {
- return ! is_null($value);
- });
- }
-
- /**
- * Get the database driver from the URL.
- *
- * @param array $url
- * @return string|null
- */
- protected function getDriver($url)
- {
- $alias = $url['scheme'] ?? null;
-
- if (! $alias) {
- return;
- }
-
- return static::$driverAliases[$alias] ?? $alias;
- }
-
- /**
- * Get the database name from the URL.
- *
- * @param array $url
- * @return string|null
- */
- protected function getDatabase($url)
- {
- $path = $url['path'] ?? null;
-
- return $path ? substr($path, 1) : null;
- }
-
- /**
- * Get all of the additional database options from the query string.
- *
- * @param array $url
- * @return array
- */
- protected function getQueryOptions($url)
- {
- $queryString = $url['query'] ?? null;
-
- if (! $queryString) {
- return [];
- }
-
- $query = [];
-
- parse_str($queryString, $query);
-
- return $this->parseStringsToNativeTypes($query);
- }
-
- /**
- * Parse the string URL to an array of components.
- *
- * @param string $url
- * @return array
- */
- protected function parseUrl($url)
- {
- $url = preg_replace('#^(sqlite3?):///#', '$1://null/', $url);
-
- $parsedUrl = parse_url($url);
-
- if ($parsedUrl === false) {
- throw new InvalidArgumentException('The database configuration URL is malformed.');
- }
-
- return $this->parseStringsToNativeTypes(
- array_map('rawurldecode', $parsedUrl)
- );
- }
-
- /**
- * Convert string casted values to their native types.
- *
- * @param mixed $value
- * @return mixed
- */
- protected function parseStringsToNativeTypes($value)
- {
- if (is_array($value)) {
- return array_map([$this, 'parseStringsToNativeTypes'], $value);
- }
-
- if (! is_string($value)) {
- return $value;
- }
-
- $parsedValue = json_decode($value, true);
-
- if (json_last_error() === JSON_ERROR_NONE) {
- return $parsedValue;
- }
-
- return $value;
- }
-
- /**
- * Get all of the current drivers aliases.
- *
- * @return array
- */
- public static function getDriverAliases()
- {
- return static::$driverAliases;
- }
-
- /**
- * Add the given driver alias to the driver aliases array.
- *
- * @param string $alias
- * @param string $driver
- * @return void
- */
- public static function addDriverAlias($alias, $driver)
- {
- static::$driverAliases[$alias] = $driver;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Carbon\Factory;
-use InvalidArgumentException;
-
-/**
- * @see https://carbon.nesbot.com/docs/
- * @see https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Factory.php
- *
- * @method static Carbon create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null)
- * @method static Carbon createFromDate($year = null, $month = null, $day = null, $tz = null)
- * @method static Carbon|false createFromFormat($format, $time, $tz = null)
- * @method static Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null)
- * @method static Carbon createFromTimeString($time, $tz = null)
- * @method static Carbon createFromTimestamp($timestamp, $tz = null)
- * @method static Carbon createFromTimestampMs($timestamp, $tz = null)
- * @method static Carbon createFromTimestampUTC($timestamp)
- * @method static Carbon createMidnightDate($year = null, $month = null, $day = null, $tz = null)
- * @method static Carbon|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
- * @method static Carbon disableHumanDiffOption($humanDiffOption)
- * @method static Carbon enableHumanDiffOption($humanDiffOption)
- * @method static mixed executeWithLocale($locale, $func)
- * @method static Carbon fromSerialized($value)
- * @method static array getAvailableLocales()
- * @method static array getDays()
- * @method static int getHumanDiffOptions()
- * @method static array getIsoUnits()
- * @method static Carbon getLastErrors()
- * @method static string getLocale()
- * @method static int getMidDayAt()
- * @method static Carbon getTestNow()
- * @method static \Symfony\Component\Translation\TranslatorInterface getTranslator()
- * @method static int getWeekEndsAt()
- * @method static int getWeekStartsAt()
- * @method static array getWeekendDays()
- * @method static bool hasFormat($date, $format)
- * @method static bool hasMacro($name)
- * @method static bool hasRelativeKeywords($time)
- * @method static bool hasTestNow()
- * @method static Carbon instance($date)
- * @method static bool isImmutable()
- * @method static bool isModifiableUnit($unit)
- * @method static Carbon isMutable()
- * @method static bool isStrictModeEnabled()
- * @method static bool localeHasDiffOneDayWords($locale)
- * @method static bool localeHasDiffSyntax($locale)
- * @method static bool localeHasDiffTwoDayWords($locale)
- * @method static bool localeHasPeriodSyntax($locale)
- * @method static bool localeHasShortUnits($locale)
- * @method static void macro($name, $macro)
- * @method static Carbon|null make($var)
- * @method static Carbon maxValue()
- * @method static Carbon minValue()
- * @method static void mixin($mixin)
- * @method static Carbon now($tz = null)
- * @method static Carbon parse($time = null, $tz = null)
- * @method static string pluralUnit(string $unit)
- * @method static void resetMonthsOverflow()
- * @method static void resetToStringFormat()
- * @method static void resetYearsOverflow()
- * @method static void serializeUsing($callback)
- * @method static Carbon setHumanDiffOptions($humanDiffOptions)
- * @method static bool setLocale($locale)
- * @method static void setMidDayAt($hour)
- * @method static Carbon setTestNow($testNow = null)
- * @method static void setToStringFormat($format)
- * @method static void setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator)
- * @method static Carbon setUtf8($utf8)
- * @method static void setWeekEndsAt($day)
- * @method static void setWeekStartsAt($day)
- * @method static void setWeekendDays($days)
- * @method static bool shouldOverflowMonths()
- * @method static bool shouldOverflowYears()
- * @method static string singularUnit(string $unit)
- * @method static Carbon today($tz = null)
- * @method static Carbon tomorrow($tz = null)
- * @method static void useMonthsOverflow($monthsOverflow = true)
- * @method static Carbon useStrictMode($strictModeEnabled = true)
- * @method static void useYearsOverflow($yearsOverflow = true)
- * @method static Carbon yesterday($tz = null)
- */
-class DateFactory
-{
- /**
- * The default class that will be used for all created dates.
- *
- * @var string
- */
- const DEFAULT_CLASS_NAME = Carbon::class;
-
- /**
- * The type (class) of dates that should be created.
- *
- * @var string
- */
- protected static $dateClass;
-
- /**
- * This callable may be used to intercept date creation.
- *
- * @var callable
- */
- protected static $callable;
-
- /**
- * The Carbon factory that should be used when creating dates.
- *
- * @var object
- */
- protected static $factory;
-
- /**
- * Use the given handler when generating dates (class name, callable, or factory).
- *
- * @param mixed $handler
- *
- * @throws \InvalidArgumentException
- */
- public static function use($handler)
- {
- if (is_callable($handler) && is_object($handler)) {
- return static::useCallable($handler);
- } elseif (is_string($handler)) {
- return static::useClass($handler);
- } elseif ($handler instanceof Factory) {
- return static::useFactory($handler);
- }
-
- throw new InvalidArgumentException('Invalid date creation handler. Please provide a class name, callable, or Carbon factory.');
- }
-
- /**
- * Use the default date class when generating dates.
- *
- * @return void
- */
- public static function useDefault()
- {
- static::$dateClass = null;
- static::$callable = null;
- static::$factory = null;
- }
-
- /**
- * Execute the given callable on each date creation.
- *
- * @param callable $callable
- * @return void
- */
- public static function useCallable(callable $callable)
- {
- static::$callable = $callable;
-
- static::$dateClass = null;
- static::$factory = null;
- }
-
- /**
- * Use the given date type (class) when generating dates.
- *
- * @param string $dateClass
- * @return void
- */
- public static function useClass($dateClass)
- {
- static::$dateClass = $dateClass;
-
- static::$factory = null;
- static::$callable = null;
- }
-
- /**
- * Use the given Carbon factory when generating dates.
- *
- * @param object $factory
- * @return void
- */
- public static function useFactory($factory)
- {
- static::$factory = $factory;
-
- static::$dateClass = null;
- static::$callable = null;
- }
-
- /**
- * Handle dynamic calls to generate dates.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- *
- * @throws \RuntimeException
- */
- public function __call($method, $parameters)
- {
- $defaultClassName = static::DEFAULT_CLASS_NAME;
-
- // Using callable to generate dates...
- if (static::$callable) {
- return call_user_func(static::$callable, $defaultClassName::$method(...$parameters));
- }
-
- // Using Carbon factory to generate dates...
- if (static::$factory) {
- return static::$factory->$method(...$parameters);
- }
-
- $dateClass = static::$dateClass ?: $defaultClassName;
-
- // Check if date can be created using public class method...
- if (method_exists($dateClass, $method) ||
- method_exists($dateClass, 'hasMacro') && $dateClass::hasMacro($method)) {
- return $dateClass::$method(...$parameters);
- }
-
- // If that fails, create the date with the default class..
- $date = $defaultClassName::$method(...$parameters);
-
- // If the configured class has an "instance" method, we'll try to pass our date into there...
- if (method_exists($dateClass, 'instance')) {
- return $dateClass::instance($date);
- }
-
- // Otherwise, assume the configured class has a DateTime compatible constructor...
- return new $dateClass($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static string version()
- * @method static string basePath()
- * @method static string bootstrapPath(string $path = '')
- * @method static string configPath(string $path = '')
- * @method static string databasePath(string $path = '')
- * @method static string environmentPath()
- * @method static string resourcePath(string $path = '')
- * @method static string storagePath(string $path = '')
- * @method static string|bool environment(string|array ...$environments)
- * @method static bool runningInConsole()
- * @method static bool runningUnitTests()
- * @method static bool isDownForMaintenance()
- * @method static void registerConfiguredProviders()
- * @method static \Illuminate\Support\ServiceProvider register(\Illuminate\Support\ServiceProvider|string $provider, bool $force = false)
- * @method static void registerDeferredProvider(string $provider, string $service = null)
- * @method static \Illuminate\Support\ServiceProvider resolveProvider(string $provider)
- * @method static void boot()
- * @method static void booting(callable $callback)
- * @method static void booted(callable $callback)
- * @method static void bootstrapWith(array $bootstrappers)
- * @method static bool configurationIsCached()
- * @method static string detectEnvironment(callable $callback)
- * @method static string environmentFile()
- * @method static string environmentFilePath()
- * @method static string getCachedConfigPath()
- * @method static string getCachedServicesPath()
- * @method static string getCachedPackagesPath()
- * @method static string getCachedRoutesPath()
- * @method static string getLocale()
- * @method static string getNamespace()
- * @method static array getProviders(\Illuminate\Support\ServiceProvider|string $provider)
- * @method static bool hasBeenBootstrapped()
- * @method static void loadDeferredProviders()
- * @method static \Illuminate\Contracts\Foundation\Application loadEnvironmentFrom(string $file)
- * @method static bool routesAreCached()
- * @method static void setLocale(string $locale)
- * @method static bool shouldSkipMiddleware()
- * @method static void terminate()
- *
- * @see \Illuminate\Contracts\Foundation\Application
- */
-class App extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'app';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract;
-
-/**
- * @method static int handle(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface|null $output = null)
- * @method static int call(string $command, array $parameters = [], \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer = null)
- * @method static \Illuminate\Foundation\Bus\PendingDispatch queue(string $command, array $parameters = [])
- * @method static array all()
- * @method static string output()
- * @method static void terminate(\Symfony\Component\Console\Input\InputInterface $input, int $status)
- *
- * @see \Illuminate\Contracts\Console\Kernel
- */
-class Artisan extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return ConsoleKernelContract::class;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static mixed guard(string|null $name = null)
- * @method static void shouldUse(string $name);
- * @method static bool check()
- * @method static bool guest()
- * @method static \Illuminate\Contracts\Auth\Authenticatable|null user()
- * @method static int|null id()
- * @method static bool validate(array $credentials = [])
- * @method static void setUser(\Illuminate\Contracts\Auth\Authenticatable $user)
- * @method static bool attempt(array $credentials = [], bool $remember = false)
- * @method static bool once(array $credentials = [])
- * @method static void login(\Illuminate\Contracts\Auth\Authenticatable $user, bool $remember = false)
- * @method static \Illuminate\Contracts\Auth\Authenticatable loginUsingId(mixed $id, bool $remember = false)
- * @method static bool onceUsingId(mixed $id)
- * @method static bool viaRemember()
- * @method static void logout()
- * @method static \Symfony\Component\HttpFoundation\Response|null onceBasic(string $field = 'email',array $extraConditions = [])
- * @method static null|bool logoutOtherDevices(string $password, string $attribute = 'password')
- * @method static \Illuminate\Contracts\Auth\UserProvider|null createUserProvider(string $provider = null)
- * @method static \Illuminate\Auth\AuthManager extend(string $driver, \Closure $callback)
- * @method static \Illuminate\Auth\AuthManager provider(string $name, \Closure $callback)
- *
- * @see \Illuminate\Auth\AuthManager
- * @see \Illuminate\Contracts\Auth\Factory
- * @see \Illuminate\Contracts\Auth\Guard
- * @see \Illuminate\Contracts\Auth\StatefulGuard
- */
-class Auth extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'auth';
- }
-
- /**
- * Register the typical authentication routes for an application.
- *
- * @param array $options
- * @return void
- */
- public static function routes(array $options = [])
- {
- static::$app->make('router')->auth($options);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static void compile(string|null $path = null)
- * @method static string getPath()
- * @method static void setPath(string $path)
- * @method static string compileString(string $value)
- * @method static string stripParentheses(string $expression)
- * @method static void extend(callable $compiler)
- * @method static array getExtensions()
- * @method static void if(string $name, callable $callback)
- * @method static bool check(string $name, array ...$parameters)
- * @method static void component(string $path, string|null $alias = null)
- * @method static void include(string $path, string|null $alias = null)
- * @method static void directive(string $name, callable $handler)
- * @method static array getCustomDirectives()
- * @method static void setEchoFormat(string $format)
- * @method static void withDoubleEncoding()
- * @method static void withoutDoubleEncoding()
- *
- * @see \Illuminate\View\Compilers\BladeCompiler
- */
-class Blade extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'blade.compiler';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Contracts\Broadcasting\Factory as BroadcastingFactoryContract;
-
-/**
- * @method static void connection($name = null);
- * @method static \Illuminate\Broadcasting\Broadcasters\Broadcaster channel(string $channel, callable|string $callback)
- * @method static mixed auth(\Illuminate\Http\Request $request)
- *
- * @see \Illuminate\Contracts\Broadcasting\Factory
- */
-class Broadcast extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return BroadcastingFactoryContract::class;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Support\Testing\Fakes\BusFake;
-use Illuminate\Contracts\Bus\Dispatcher as BusDispatcherContract;
-
-/**
- * @method static mixed dispatch($command)
- * @method static mixed dispatchNow($command, $handler = null)
- * @method static bool hasCommandHandler($command)
- * @method static bool|mixed getCommandHandler($command)
- * @method static \Illuminate\Contracts\Bus\Dispatcher pipeThrough(array $pipes)
- * @method static \Illuminate\Contracts\Bus\Dispatcher map(array $map)
- *
- * @see \Illuminate\Contracts\Bus\Dispatcher
- */
-class Bus extends Facade
-{
- /**
- * Replace the bound instance with a fake.
- *
- * @return \Illuminate\Support\Testing\Fakes\BusFake
- */
- public static function fake()
- {
- static::swap($fake = new BusFake);
-
- return $fake;
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return BusDispatcherContract::class;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Contracts\Cache\Repository store(string|null $name = null)
- * @method static bool has(string $key)
- * @method static bool missing(string $key)
- * @method static mixed get(string $key, mixed $default = null)
- * @method static mixed pull(string $key, mixed $default = null)
- * @method static bool put(string $key, $value, \DateTimeInterface|\DateInterval|int $ttl)
- * @method static bool add(string $key, $value, \DateTimeInterface|\DateInterval|int $ttl)
- * @method static int|bool increment(string $key, $value = 1)
- * @method static int|bool decrement(string $key, $value = 1)
- * @method static bool forever(string $key, $value)
- * @method static mixed remember(string $key, \DateTimeInterface|\DateInterval|int $ttl, \Closure $callback)
- * @method static mixed sear(string $key, \Closure $callback)
- * @method static mixed rememberForever(string $key, \Closure $callback)
- * @method static bool forget(string $key)
- * @method static \Illuminate\Contracts\Cache\Store getStore()
- *
- * @see \Illuminate\Cache\CacheManager
- * @see \Illuminate\Cache\Repository
- */
-class Cache extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'cache';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static bool has($key)
- * @method static mixed get($key, $default = null)
- * @method static array all()
- * @method static void set($key, $value = null)
- * @method static void prepend($key, $value)
- * @method static void push($key, $value)
- *
- * @see \Illuminate\Config\Repository
- */
-class Config extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'config';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static void queue(...$parameters)
- * @method static unqueue($name)
- * @method static array getQueuedCookies()
- *
- * @see \Illuminate\Cookie\CookieJar
- */
-class Cookie extends Facade
-{
- /**
- * Determine if a cookie exists on the request.
- *
- * @param string $key
- * @return bool
- */
- public static function has($key)
- {
- return ! is_null(static::$app['request']->cookie($key, null));
- }
-
- /**
- * Retrieve a cookie from the request.
- *
- * @param string $key
- * @param mixed $default
- * @return string|array|null
- */
- public static function get($key = null, $default = null)
- {
- return static::$app['request']->cookie($key, $default);
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'cookie';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static bool supported(string $key, string $cipher)
- * @method static string generateKey(string $cipher)
- * @method static string encrypt(mixed $value, bool $serialize = true)
- * @method static string encryptString(string $value)
- * @method static mixed decrypt(string $payload, bool $unserialize = true)
- * @method static string decryptString(string $payload)
- * @method static string getKey()
- *
- * @see \Illuminate\Encryption\Encrypter
- */
-class Crypt extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'encrypter';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Database\ConnectionInterface connection(string $name = null)
- * @method static string getDefaultConnection()
- * @method static void setDefaultConnection(string $name)
- * @method static \Illuminate\Database\Query\Builder table(string $table)
- * @method static \Illuminate\Database\Query\Expression raw($value)
- * @method static mixed selectOne(string $query, array $bindings = [])
- * @method static array select(string $query, array $bindings = [])
- * @method static bool insert(string $query, array $bindings = [])
- * @method static int update(string $query, array $bindings = [])
- * @method static int delete(string $query, array $bindings = [])
- * @method static bool statement(string $query, array $bindings = [])
- * @method static int affectingStatement(string $query, array $bindings = [])
- * @method static bool unprepared(string $query)
- * @method static array prepareBindings(array $bindings)
- * @method static mixed transaction(\Closure $callback, int $attempts = 1)
- * @method static void beginTransaction()
- * @method static void commit()
- * @method static void rollBack()
- * @method static int transactionLevel()
- * @method static array pretend(\Closure $callback)
- *
- * @see \Illuminate\Database\DatabaseManager
- * @see \Illuminate\Database\Connection
- */
-class DB extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'db';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Support\DateFactory;
-
-/**
- * @see https://carbon.nesbot.com/docs/
- * @see https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Factory.php
- *
- * @method static \Illuminate\Support\Carbon create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null)
- * @method static \Illuminate\Support\Carbon createFromDate($year = null, $month = null, $day = null, $tz = null)
- * @method static \Illuminate\Support\Carbon|false createFromFormat($format, $time, $tz = null)
- * @method static \Illuminate\Support\Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null)
- * @method static \Illuminate\Support\Carbon createFromTimeString($time, $tz = null)
- * @method static \Illuminate\Support\Carbon createFromTimestamp($timestamp, $tz = null)
- * @method static \Illuminate\Support\Carbon createFromTimestampMs($timestamp, $tz = null)
- * @method static \Illuminate\Support\Carbon createFromTimestampUTC($timestamp)
- * @method static \Illuminate\Support\Carbon createMidnightDate($year = null, $month = null, $day = null, $tz = null)
- * @method static \Illuminate\Support\Carbon|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
- * @method static \Illuminate\Support\Carbon disableHumanDiffOption($humanDiffOption)
- * @method static \Illuminate\Support\Carbon enableHumanDiffOption($humanDiffOption)
- * @method static mixed executeWithLocale($locale, $func)
- * @method static \Illuminate\Support\Carbon fromSerialized($value)
- * @method static array getAvailableLocales()
- * @method static array getDays()
- * @method static int getHumanDiffOptions()
- * @method static array getIsoUnits()
- * @method static \Illuminate\Support\Carbon getLastErrors()
- * @method static string getLocale()
- * @method static int getMidDayAt()
- * @method static \Illuminate\Support\Carbon getTestNow()
- * @method static \Symfony\Component\Translation\TranslatorInterface getTranslator()
- * @method static int getWeekEndsAt()
- * @method static int getWeekStartsAt()
- * @method static array getWeekendDays()
- * @method static bool hasFormat($date, $format)
- * @method static bool hasMacro($name)
- * @method static bool hasRelativeKeywords($time)
- * @method static bool hasTestNow()
- * @method static \Illuminate\Support\Carbon instance($date)
- * @method static bool isImmutable()
- * @method static bool isModifiableUnit($unit)
- * @method static \Illuminate\Support\Carbon isMutable()
- * @method static bool isStrictModeEnabled()
- * @method static bool localeHasDiffOneDayWords($locale)
- * @method static bool localeHasDiffSyntax($locale)
- * @method static bool localeHasDiffTwoDayWords($locale)
- * @method static bool localeHasPeriodSyntax($locale)
- * @method static bool localeHasShortUnits($locale)
- * @method static void macro($name, $macro)
- * @method static \Illuminate\Support\Carbon|null make($var)
- * @method static \Illuminate\Support\Carbon maxValue()
- * @method static \Illuminate\Support\Carbon minValue()
- * @method static void mixin($mixin)
- * @method static \Illuminate\Support\Carbon now($tz = null)
- * @method static \Illuminate\Support\Carbon parse($time = null, $tz = null)
- * @method static string pluralUnit(string $unit)
- * @method static void resetMonthsOverflow()
- * @method static void resetToStringFormat()
- * @method static void resetYearsOverflow()
- * @method static void serializeUsing($callback)
- * @method static \Illuminate\Support\Carbon setHumanDiffOptions($humanDiffOptions)
- * @method static bool setLocale($locale)
- * @method static void setMidDayAt($hour)
- * @method static \Illuminate\Support\Carbon setTestNow($testNow = null)
- * @method static void setToStringFormat($format)
- * @method static void setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator)
- * @method static \Illuminate\Support\Carbon setUtf8($utf8)
- * @method static void setWeekEndsAt($day)
- * @method static void setWeekStartsAt($day)
- * @method static void setWeekendDays($days)
- * @method static bool shouldOverflowMonths()
- * @method static bool shouldOverflowYears()
- * @method static string singularUnit(string $unit)
- * @method static \Illuminate\Support\Carbon today($tz = null)
- * @method static \Illuminate\Support\Carbon tomorrow($tz = null)
- * @method static void useMonthsOverflow($monthsOverflow = true)
- * @method static \Illuminate\Support\Carbon useStrictMode($strictModeEnabled = true)
- * @method static void useYearsOverflow($yearsOverflow = true)
- * @method static \Illuminate\Support\Carbon yesterday($tz = null)
- */
-class Date extends Facade
-{
- const DEFAULT_FACADE = DateFactory::class;
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- *
- * @throws \RuntimeException
- */
- protected static function getFacadeAccessor()
- {
- return 'date';
- }
-
- /**
- * Resolve the facade root instance from the container.
- *
- * @param string $name
- * @return mixed
- */
- protected static function resolveFacadeInstance($name)
- {
- if (! isset(static::$resolvedInstance[$name]) && ! isset(static::$app, static::$app[$name])) {
- $class = static::DEFAULT_FACADE;
-
- static::swap(new $class);
- }
-
- return parent::resolveFacadeInstance($name);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Database\Eloquent\Model;
-use Illuminate\Support\Testing\Fakes\EventFake;
-
-/**
- * @method static void listen(string|array $events, mixed $listener)
- * @method static bool hasListeners(string $eventName)
- * @method static void push(string $event, array $payload = [])
- * @method static void flush(string $event)
- * @method static void subscribe(object|string $subscriber)
- * @method static array|null until(string|object $event, mixed $payload = [])
- * @method static array|null dispatch(string|object $event, mixed $payload = [], bool $halt = false)
- * @method static array getListeners(string $eventName)
- * @method static \Closure makeListener(\Closure|string $listener, bool $wildcard = false)
- * @method static \Closure createClassListener(string $listener, bool $wildcard = false)
- * @method static void forget(string $event)
- * @method static void forgetPushed()
- * @method static \Illuminate\Events\Dispatcher setQueueResolver(callable $resolver)
- *
- * @see \Illuminate\Events\Dispatcher
- */
-class Event extends Facade
-{
- /**
- * Replace the bound instance with a fake.
- *
- * @param array|string $eventsToFake
- * @return \Illuminate\Support\Testing\Fakes\EventFake
- */
- public static function fake($eventsToFake = [])
- {
- static::swap($fake = new EventFake(static::getFacadeRoot(), $eventsToFake));
-
- Model::setEventDispatcher($fake);
-
- return $fake;
- }
-
- /**
- * Replace the bound instance with a fake during the given callable's execution.
- *
- * @param callable $callable
- * @param array $eventsToFake
- * @return callable
- */
- public static function fakeFor(callable $callable, array $eventsToFake = [])
- {
- $originalDispatcher = static::getFacadeRoot();
-
- static::fake($eventsToFake);
-
- return tap($callable(), function () use ($originalDispatcher) {
- static::swap($originalDispatcher);
-
- Model::setEventDispatcher($originalDispatcher);
- });
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'events';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Closure;
-use Mockery;
-use RuntimeException;
-use Mockery\MockInterface;
-
-abstract class Facade
-{
- /**
- * The application instance being facaded.
- *
- * @var \Illuminate\Contracts\Foundation\Application
- */
- protected static $app;
-
- /**
- * The resolved object instances.
- *
- * @var array
- */
- protected static $resolvedInstance;
-
- /**
- * Run a Closure when the facade has been resolved.
- *
- * @param \Closure $callback
- * @return void
- */
- public static function resolved(Closure $callback)
- {
- static::$app->afterResolving(static::getFacadeAccessor(), function ($service) use ($callback) {
- $callback($service);
- });
- }
-
- /**
- * Convert the facade into a Mockery spy.
- *
- * @return \Mockery\MockInterface
- */
- public static function spy()
- {
- if (! static::isMock()) {
- $class = static::getMockableClass();
-
- return tap($class ? Mockery::spy($class) : Mockery::spy(), function ($spy) {
- static::swap($spy);
- });
- }
- }
-
- /**
- * Initiate a mock expectation on the facade.
- *
- * @return \Mockery\Expectation
- */
- public static function shouldReceive()
- {
- $name = static::getFacadeAccessor();
-
- $mock = static::isMock()
- ? static::$resolvedInstance[$name]
- : static::createFreshMockInstance();
-
- return $mock->shouldReceive(...func_get_args());
- }
-
- /**
- * Create a fresh mock instance for the given class.
- *
- * @return \Mockery\Expectation
- */
- protected static function createFreshMockInstance()
- {
- return tap(static::createMock(), function ($mock) {
- static::swap($mock);
-
- $mock->shouldAllowMockingProtectedMethods();
- });
- }
-
- /**
- * Create a fresh mock instance for the given class.
- *
- * @return \Mockery\MockInterface
- */
- protected static function createMock()
- {
- $class = static::getMockableClass();
-
- return $class ? Mockery::mock($class) : Mockery::mock();
- }
-
- /**
- * Determines whether a mock is set as the instance of the facade.
- *
- * @return bool
- */
- protected static function isMock()
- {
- $name = static::getFacadeAccessor();
-
- return isset(static::$resolvedInstance[$name]) &&
- static::$resolvedInstance[$name] instanceof MockInterface;
- }
-
- /**
- * Get the mockable class for the bound instance.
- *
- * @return string|null
- */
- protected static function getMockableClass()
- {
- if ($root = static::getFacadeRoot()) {
- return get_class($root);
- }
- }
-
- /**
- * Hotswap the underlying instance behind the facade.
- *
- * @param mixed $instance
- * @return void
- */
- public static function swap($instance)
- {
- static::$resolvedInstance[static::getFacadeAccessor()] = $instance;
-
- if (isset(static::$app)) {
- static::$app->instance(static::getFacadeAccessor(), $instance);
- }
- }
-
- /**
- * Get the root object behind the facade.
- *
- * @return mixed
- */
- public static function getFacadeRoot()
- {
- return static::resolveFacadeInstance(static::getFacadeAccessor());
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- *
- * @throws \RuntimeException
- */
- protected static function getFacadeAccessor()
- {
- throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
- }
-
- /**
- * Resolve the facade root instance from the container.
- *
- * @param object|string $name
- * @return mixed
- */
- protected static function resolveFacadeInstance($name)
- {
- if (is_object($name)) {
- return $name;
- }
-
- if (isset(static::$resolvedInstance[$name])) {
- return static::$resolvedInstance[$name];
- }
-
- return static::$resolvedInstance[$name] = static::$app[$name];
- }
-
- /**
- * Clear a resolved facade instance.
- *
- * @param string $name
- * @return void
- */
- public static function clearResolvedInstance($name)
- {
- unset(static::$resolvedInstance[$name]);
- }
-
- /**
- * Clear all of the resolved instances.
- *
- * @return void
- */
- public static function clearResolvedInstances()
- {
- static::$resolvedInstance = [];
- }
-
- /**
- * Get the application instance behind the facade.
- *
- * @return \Illuminate\Contracts\Foundation\Application
- */
- public static function getFacadeApplication()
- {
- return static::$app;
- }
-
- /**
- * Set the application instance.
- *
- * @param \Illuminate\Contracts\Foundation\Application $app
- * @return void
- */
- public static function setFacadeApplication($app)
- {
- static::$app = $app;
- }
-
- /**
- * Handle dynamic, static calls to the object.
- *
- * @param string $method
- * @param array $args
- * @return mixed
- *
- * @throws \RuntimeException
- */
- public static function __callStatic($method, $args)
- {
- $instance = static::getFacadeRoot();
-
- if (! $instance) {
- throw new RuntimeException('A facade root has not been set.');
- }
-
- return $instance->$method(...$args);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static bool exists(string $path)
- * @method static string get(string $path, bool $lock = false)
- * @method static string sharedGet(string $path)
- * @method static mixed getRequire(string $path)
- * @method static mixed requireOnce(string $file)
- * @method static string hash(string $path)
- * @method static int|bool put(string $path, string $contents, bool $lock = false)
- * @method static void replace(string $path, string $content)
- * @method static int prepend(string $path, string $data)
- * @method static int append(string $path, string $data)
- * @method static mixed chmod(string $path, int|null $mode = null)
- * @method static bool delete(string|array $paths)
- * @method static bool move(string $path, string $target)
- * @method static bool copy(string $path, string $target)
- * @method static void link(string $target, string $link)
- * @method static string name(string $path)
- * @method static string basename(string $path)
- * @method static string dirname(string $path)
- * @method static string extension(string $path)
- * @method static string type(string $path)
- * @method static string|false mimeType(string $path)
- * @method static int size(string $path)
- * @method static int lastModified(string $path)
- * @method static bool isDirectory(string $directory)
- * @method static bool isReadable(string $path)
- * @method static bool isWritable(string $path)
- * @method static bool isFile(string $file)
- * @method static array glob(string $pattern, int $flags = 0)
- * @method static \Symfony\Component\Finder\SplFileInfo[] files(string $directory, bool $hidden = false)
- * @method static \Symfony\Component\Finder\SplFileInfo[] allFiles(string $directory, bool $hidden = false)
- * @method static array directories(string $directory)
- * @method static bool makeDirectory(string $path, int $mode = 0755, bool $recursive = false, bool $force = false)
- * @method static bool moveDirectory(string $from, string $to, bool $overwrite = false)
- * @method static bool copyDirectory(string $directory, string $destination, int|null $options = null)
- * @method static bool deleteDirectory(string $directory, bool $preserve = false)
- * @method static bool deleteDirectories(string $directory)
- * @method static bool cleanDirectory(string $directory)
- *
- * @see \Illuminate\Filesystem\Filesystem
- */
-class File extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'files';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Contracts\Auth\Access\Gate as GateContract;
-
-/**
- * @method static bool has(string $ability)
- * @method static \Illuminate\Contracts\Auth\Access\Gate define(string $ability, callable|string $callback)
- * @method static \Illuminate\Contracts\Auth\Access\Gate policy(string $class, string $policy)
- * @method static \Illuminate\Contracts\Auth\Access\Gate before(callable $callback)
- * @method static \Illuminate\Contracts\Auth\Access\Gate after(callable $callback)
- * @method static bool allows(string $ability, array|mixed $arguments = [])
- * @method static bool denies(string $ability, array|mixed $arguments = [])
- * @method static bool check(iterable|string $abilities, array|mixed $arguments = [])
- * @method static bool any(iterable|string $abilities, array|mixed $arguments = [])
- * @method static \Illuminate\Auth\Access\Response authorize(string $ability, array|mixed $arguments = [])
- * @method static mixed raw(string $ability, array|mixed $arguments = [])
- * @method static mixed getPolicyFor(object|string $class)
- * @method static \Illuminate\Contracts\Auth\Access\Gate forUser(\Illuminate\Contracts\Auth\Authenticatable|mixed $user)
- * @method static array abilities()
- *
- * @see \Illuminate\Contracts\Auth\Access\Gate
- */
-class Gate extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return GateContract::class;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static array info(string $hashedValue)
- * @method static string make(string $value, array $options = [])
- * @method static bool check(string $value, string $hashedValue, array $options = [])
- * @method static bool needsRehash(string $hashedValue, array $options = [])
- *
- * @see \Illuminate\Hashing\HashManager
- */
-class Hash extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'hash';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static bool matchesType(string $actual, string $type)
- * @method static bool isJson()
- * @method static bool expectsJson()
- * @method static bool wantsJson()
- * @method static bool accepts(string|array $contentTypes)
- * @method static bool prefers(string|array $contentTypes)
- * @method static bool acceptsAnyContentType()
- * @method static bool acceptsJson()
- * @method static bool acceptsHtml()
- * @method static string format($default = 'html')
- * @method static string|array old(string|null $key = null, string|array|null $default = null)
- * @method static void flash()
- * @method static void flashOnly(array|mixed $keys)
- * @method static void flashExcept(array|mixed $keys)
- * @method static void flush()
- * @method static string|array|null server(string|null $key = null, string|array|null $default = null)
- * @method static bool hasHeader(string $key)
- * @method static string|array|null header(string|null $key = null, string|array|null $default = null)
- * @method static string|null bearerToken()
- * @method static bool exists(string|array $key)
- * @method static bool has(string|array $key)
- * @method static bool hasAny(string|array $key)
- * @method static bool filled(string|array $key)
- * @method static bool anyFilled(string|array $key)
- * @method static array keys()
- * @method static array all(array|mixed|null $keys = null)
- * @method static string|array|null input(string|null $key = null, string|array|null $default = null)
- * @method static array only(array|mixed $keys)
- * @method static array except(array|mixed $keys)
- * @method static string|array|null query(string|null $key = null, string|array|null $default = null)
- * @method static string|array|null post(string|null $key = null, string|array|null $default = null)
- * @method static bool hasCookie(string $key)
- * @method static string|array|null cookie(string|null $key = null, string|array|null $default = null)
- * @method static array allFiles()
- * @method static bool hasFile(string $key)
- * @method static \Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]|array|null file(string|null $key = null, mixed $default = null)
- * @method static \Illuminate\Http\Request capture()
- * @method static \Illuminate\Http\Request instance()
- * @method static string method()
- * @method static string root()
- * @method static string url()
- * @method static string fullUrl()
- * @method static string fullUrlWithQuery(array $query)
- * @method static string path()
- * @method static string decodedPath()
- * @method static string|null segment(int $index, string|null $default = null)
- * @method static array segments()
- * @method static bool is(mixed ...$patterns)
- * @method static bool routeIs(mixed ...$patterns)
- * @method static bool fullUrlIs(mixed ...$patterns)
- * @method static bool ajax()
- * @method static bool pjax()
- * @method static bool prefetch()
- * @method static bool secure()
- * @method static string|null ip()
- * @method static array ips()
- * @method static string userAgent()
- * @method static \Illuminate\Http\Request merge(array $input)
- * @method static \Illuminate\Http\Request replace(array $input)
- * @method static \Symfony\Component\HttpFoundation\ParameterBag|mixed json(string|null $key = null, mixed $default = null)
- * @method static \Illuminate\Http\Request createFrom(\Illuminate\Http\Request $from, \Illuminate\Http\Request|null $to = null)
- * @method static \Illuminate\Http\Request createFromBase(\Symfony\Component\HttpFoundation\Request $request)
- * @method static \Illuminate\Http\Request duplicate(array|null $query = null, array|null $request = null, array|null $attributes = null, array|null $cookies = null, array|null $files = null, array|null $server = null)
- * @method static mixed filterFiles(mixed $files)
- * @method static \Illuminate\Session\Store session()
- * @method static \Illuminate\Session\Store|null getSession()
- * @method static void setLaravelSession(\Illuminate\Contracts\Session\Session $session)
- * @method static mixed user(string|null $guard = null)
- * @method static \Illuminate\Routing\Route|object|string route(string|null $param = null, string|null $default = null)
- * @method static string fingerprint()
- * @method static \Illuminate\Http\Request setJson(\Symfony\Component\HttpFoundation\ParameterBag $json)
- * @method static \Closure getUserResolver()
- * @method static \Illuminate\Http\Request setUserResolver(\Closure $callback)
- * @method static \Closure getRouteResolver()
- * @method static \Illuminate\Http\Request setRouteResolver(\Closure $callback)
- * @method static array toArray()
- * @method static bool offsetExists(string $offset)
- * @method static mixed offsetGet(string $offset)
- * @method static void offsetSet(string $offset, mixed $value)
- * @method static void offsetUnset(string $offset)
- *
- * @see \Illuminate\Http\Request
- */
-class Input extends Facade
-{
- /**
- * Get an item from the input data.
- *
- * This method is used for all request verbs (GET, POST, PUT, and DELETE)
- *
- * @param string|null $key
- * @param mixed $default
- * @return mixed
- */
- public static function get($key = null, $default = null)
- {
- return static::$app['request']->input($key, $default);
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'request';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static mixed trans(string $key, array $replace = [], string $locale = null)
- * @method static string transChoice(string $key, int|array|\Countable $number, array $replace = [], string $locale = null)
- * @method static string getLocale()
- * @method static void setLocale(string $locale)
- * @method static string|array|null get(string $key, array $replace = [], string $locale = null, bool $fallback = true)
- *
- * @see \Illuminate\Translation\Translator
- */
-class Lang extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'translator';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static void emergency(string $message, array $context = [])
- * @method static void alert(string $message, array $context = [])
- * @method static void critical(string $message, array $context = [])
- * @method static void error(string $message, array $context = [])
- * @method static void warning(string $message, array $context = [])
- * @method static void notice(string $message, array $context = [])
- * @method static void info(string $message, array $context = [])
- * @method static void debug(string $message, array $context = [])
- * @method static void log($level, string $message, array $context = [])
- * @method static mixed channel(string $channel = null)
- * @method static \Psr\Log\LoggerInterface stack(array $channels, string $channel = null)
- *
- * @see \Illuminate\Log\Logger
- */
-class Log extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'log';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Support\Testing\Fakes\MailFake;
-
-/**
- * @method static \Illuminate\Mail\PendingMail to($users)
- * @method static \Illuminate\Mail\PendingMail bcc($users)
- * @method static void raw(string $text, $callback)
- * @method static void send(string|array|\Illuminate\Contracts\Mail\Mailable $view, array $data = [], \Closure|string $callback = null)
- * @method static array failures()
- * @method static mixed queue(string|array|\Illuminate\Contracts\Mail\Mailable $view, string $queue = null)
- * @method static mixed later(\DateTimeInterface|\DateInterval|int $delay, string|array|\Illuminate\Contracts\Mail\Mailable $view, string $queue = null)
- * @method static void assertSent(string $mailable, \Closure|string $callback = null)
- * @method static void assertNotSent(string $mailable, \Closure|string $callback = null)
- * @method static void assertNothingSent()
- * @method static void assertQueued(string $mailable, \Closure|string $callback = null)
- * @method static void assertNotQueued(string $mailable, \Closure|string $callback = null)
- * @method static void assertNothingQueued()
- * @method static \Illuminate\Support\Collection sent(string $mailable, \Closure|string $callback = null)
- * @method static bool hasSent(string $mailable)
- * @method static \Illuminate\Support\Collection queued(string $mailable, \Closure|string $callback = null)
- * @method static bool hasQueued(string $mailable)
- *
- * @see \Illuminate\Mail\Mailer
- * @see \Illuminate\Support\Testing\Fakes\MailFake
- */
-class Mail extends Facade
-{
- /**
- * Replace the bound instance with a fake.
- *
- * @return \Illuminate\Support\Testing\Fakes\MailFake
- */
- public static function fake()
- {
- static::swap($fake = new MailFake);
-
- return $fake;
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'mailer';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Notifications\ChannelManager;
-use Illuminate\Notifications\AnonymousNotifiable;
-use Illuminate\Support\Testing\Fakes\NotificationFake;
-
-/**
- * @method static void send(\Illuminate\Support\Collection|array|mixed $notifiables, $notification)
- * @method static void sendNow(\Illuminate\Support\Collection|array|mixed $notifiables, $notification)
- * @method static mixed channel(string|null $name = null)
- * @method static \Illuminate\Notifications\ChannelManager locale(string|null $locale)
- *
- * @see \Illuminate\Notifications\ChannelManager
- */
-class Notification extends Facade
-{
- /**
- * Replace the bound instance with a fake.
- *
- * @return \Illuminate\Support\Testing\Fakes\NotificationFake
- */
- public static function fake()
- {
- static::swap($fake = new NotificationFake);
-
- return $fake;
- }
-
- /**
- * Begin sending a notification to an anonymous notifiable.
- *
- * @param string $channel
- * @param mixed $route
- * @return \Illuminate\Notifications\AnonymousNotifiable
- */
- public static function route($channel, $route)
- {
- return (new AnonymousNotifiable)->route($channel, $route);
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return ChannelManager::class;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static string sendResetLink(array $credentials)
- * @method static mixed reset(array $credentials, \Closure $callback)
- * @method static void validator(\Closure $callback)
- * @method static bool validateNewPassword(array $credentials)
- *
- * @see \Illuminate\Auth\Passwords\PasswordBroker
- */
-class Password extends Facade
-{
- /**
- * Constant representing a successfully sent reminder.
- *
- * @var string
- */
- const RESET_LINK_SENT = 'passwords.sent';
-
- /**
- * Constant representing a successfully reset password.
- *
- * @var string
- */
- const PASSWORD_RESET = 'passwords.reset';
-
- /**
- * Constant representing the user not found response.
- *
- * @var string
- */
- const INVALID_USER = 'passwords.user';
-
- /**
- * Constant representing an invalid password.
- *
- * @var string
- */
- const INVALID_PASSWORD = 'passwords.password';
-
- /**
- * Constant representing an invalid token.
- *
- * @var string
- */
- const INVALID_TOKEN = 'passwords.token';
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'auth.password';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Support\Testing\Fakes\QueueFake;
-
-/**
- * @method static int size(string $queue = null)
- * @method static mixed push(string|object $job, mixed $data = '', $queue = null)
- * @method static mixed pushOn(string $queue, string|object $job, mixed $data = '')
- * @method static mixed pushRaw(string $payload, string $queue = null, array $options = [])
- * @method static mixed later(\DateTimeInterface|\DateInterval|int $delay, string|object $job, mixed $data = '', string $queue = null)
- * @method static mixed laterOn(string $queue, \DateTimeInterface|\DateInterval|int $delay, string|object $job, mixed $data = '')
- * @method static mixed bulk(array $jobs, mixed $data = '', string $queue = null)
- * @method static \Illuminate\Contracts\Queue\Job|null pop(string $queue = null)
- * @method static string getConnectionName()
- * @method static \Illuminate\Contracts\Queue\Queue setConnectionName(string $name)
- *
- * @see \Illuminate\Queue\QueueManager
- * @see \Illuminate\Queue\Queue
- */
-class Queue extends Facade
-{
- /**
- * Replace the bound instance with a fake.
- *
- * @return \Illuminate\Support\Testing\Fakes\QueueFake
- */
- public static function fake()
- {
- static::swap($fake = new QueueFake(static::getFacadeApplication()));
-
- return $fake;
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'queue';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Http\RedirectResponse home(int $status = 302)
- * @method static \Illuminate\Http\RedirectResponse back(int $status = 302, array $headers = [], $fallback = false)
- * @method static \Illuminate\Http\RedirectResponse refresh(int $status = 302, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse guest(string $path, int $status = 302, array $headers = [], bool $secure = null)
- * @method static intended(string $default = '/', int $status = 302, array $headers = [], bool $secure = null)
- * @method static \Illuminate\Http\RedirectResponse to(string $path, int $status = 302, array $headers = [], bool $secure = null)
- * @method static \Illuminate\Http\RedirectResponse away(string $path, int $status = 302, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse secure(string $path, int $status = 302, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse route(string $route, array $parameters = [], int $status = 302, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse action(string $action, array $parameters = [], int $status = 302, array $headers = [])
- * @method static \Illuminate\Routing\UrlGenerator getUrlGenerator()
- * @method static void setSession(\Illuminate\Session\Store $session)
- *
- * @see \Illuminate\Routing\Redirector
- */
-class Redirect extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'redirect';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Redis\Connections\Connection connection(string $name = null)
- *
- * @see \Illuminate\Redis\RedisManager
- * @see \Illuminate\Contracts\Redis\Factory
- */
-class Redis extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'redis';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Http\Request instance()
- * @method static string method()
- * @method static string root()
- * @method static string url()
- * @method static string fullUrl()
- * @method static string fullUrlWithQuery(array $query)
- * @method static string path()
- * @method static string decodedPath()
- * @method static string|null segment(int $index, string|null $default = null)
- * @method static array segments()
- * @method static bool is(...$patterns)
- * @method static bool routeIs(...$patterns)
- * @method static bool fullUrlIs(...$patterns)
- * @method static bool ajax()
- * @method static bool pjax()
- * @method static bool secure()
- * @method static string ip()
- * @method static array ips()
- * @method static string userAgent()
- * @method static \Illuminate\Http\Request merge(array $input)
- * @method static \Illuminate\Http\Request replace(array $input)
- * @method static \Symfony\Component\HttpFoundation\ParameterBag|mixed json(string $key = null, $default = null)
- * @method static \Illuminate\Session\Store session()
- * @method static \Illuminate\Session\Store|null getSession()
- * @method static void setLaravelSession(\Illuminate\Contracts\Session\Session $session)
- * @method static mixed user(string|null $guard = null)
- * @method static \Illuminate\Routing\Route|object|string route(string|null $param = null)
- * @method static string fingerprint()
- * @method static \Illuminate\Http\Request setJson(\Symfony\Component\HttpFoundation\ParameterBag $json)
- * @method static \Closure getUserResolver()
- * @method static \Illuminate\Http\Request setUserResolver(\Closure $callback)
- * @method static \Closure getRouteResolver()
- * @method static \Illuminate\Http\Request setRouteResolver(\Closure $callback)
- * @method static array toArray()
- * @method static bool offsetExists(string $offset)
- * @method static mixed offsetGet(string $offset)
- * @method static void offsetSet(string $offset, $value)
- * @method static void offsetUnset(string $offset)
- *
- * @see \Illuminate\Http\Request
- */
-class Request extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'request';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract;
-
-/**
- * @method static \Illuminate\Http\Response make(string $content = '', int $status = 200, array $headers = [])
- * @method static \Illuminate\Http\Response noContent($status = 204, array $headers = [])
- * @method static \Illuminate\Http\Response view(string $view, array $data = [], int $status = 200, array $headers = [])
- * @method static \Illuminate\Http\JsonResponse json(string|array $data = [], int $status = 200, array $headers = [], int $options = 0)
- * @method static \Illuminate\Http\JsonResponse jsonp(string $callback, string|array $data = [], int $status = 200, array $headers = [], int $options = 0)
- * @method static \Symfony\Component\HttpFoundation\StreamedResponse stream(\Closure $callback, int $status = 200, array $headers = [])
- * @method static \Symfony\Component\HttpFoundation\StreamedResponse streamDownload(\Closure $callback, string|null $name = null, array $headers = [], string|null $disposition = 'attachment')
- * @method static \Symfony\Component\HttpFoundation\BinaryFileResponse download(\SplFileInfo|string $file, string|null $name = null, array $headers = [], string|null $disposition = 'attachment')
- * @method static \Symfony\Component\HttpFoundation\BinaryFileResponse file($file, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse redirectTo(string $path, int $status = 302, array $headers = [], bool|null $secure = null)
- * @method static \Illuminate\Http\RedirectResponse redirectToRoute(string $route, array $parameters = [], int $status = 302, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse redirectToAction(string $action, array $parameters = [], int $status = 302, array $headers = [])
- * @method static \Illuminate\Http\RedirectResponse redirectGuest(string $path, int $status = 302, array $headers = [], bool|null $secure = null)
- * @method static \Illuminate\Http\RedirectResponse redirectToIntended(string $default = '/', int $status = 302, array $headers = [], bool|null $secure = null)
- *
- * @see \Illuminate\Contracts\Routing\ResponseFactory
- */
-class Response extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return ResponseFactoryContract::class;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Routing\Route get(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route post(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route put(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route delete(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route patch(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route options(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route any(string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\Route match(array|string $methods, string $uri, \Closure|array|string|callable|null $action = null)
- * @method static \Illuminate\Routing\RouteRegistrar prefix(string $prefix)
- * @method static \Illuminate\Routing\RouteRegistrar where(array $where)
- * @method static \Illuminate\Routing\PendingResourceRegistration resource(string $name, string $controller, array $options = [])
- * @method static \Illuminate\Routing\PendingResourceRegistration apiResource(string $name, string $controller, array $options = [])
- * @method static void apiResources(array $resources)
- * @method static \Illuminate\Routing\RouteRegistrar middleware(array|string|null $middleware)
- * @method static \Illuminate\Routing\Route substituteBindings(\Illuminate\Support\Facades\Route $route)
- * @method static void substituteImplicitBindings(\Illuminate\Support\Facades\Route $route)
- * @method static \Illuminate\Routing\RouteRegistrar as(string $value)
- * @method static \Illuminate\Routing\RouteRegistrar domain(string $value)
- * @method static \Illuminate\Routing\RouteRegistrar name(string $value)
- * @method static \Illuminate\Routing\RouteRegistrar namespace(string $value)
- * @method static \Illuminate\Routing\Router|\Illuminate\Routing\RouteRegistrar group(array|\Closure|string $attributes, \Closure|string $routes)
- * @method static \Illuminate\Routing\Route redirect(string $uri, string $destination, int $status = 302)
- * @method static \Illuminate\Routing\Route permanentRedirect(string $uri, string $destination)
- * @method static \Illuminate\Routing\Route view(string $uri, string $view, array $data = [])
- * @method static void bind(string $key, string|callable $binder)
- * @method static void model(string $key, string $class, \Closure|null $callback = null)
- * @method static \Illuminate\Routing\Route current()
- * @method static string|null currentRouteName()
- * @method static string|null currentRouteAction()
- *
- * @see \Illuminate\Routing\Router
- */
-class Route extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'router';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Database\Schema\Builder create(string $table, \Closure $callback)
- * @method static \Illuminate\Database\Schema\Builder drop(string $table)
- * @method static \Illuminate\Database\Schema\Builder dropIfExists(string $table)
- * @method static \Illuminate\Database\Schema\Builder table(string $table, \Closure $callback)
- * @method static \Illuminate\Database\Schema\Builder rename(string $from, string $to)
- * @method static void defaultStringLength(int $length)
- * @method static bool hasTable(string $table)
- * @method static bool hasColumn(string $table, string $column)
- * @method static bool hasColumns(string $table, array $columns)
- * @method static \Illuminate\Database\Schema\Builder disableForeignKeyConstraints()
- * @method static \Illuminate\Database\Schema\Builder enableForeignKeyConstraints()
- * @method static void registerCustomDoctrineType(string $class, string $name, string $type)
- *
- * @see \Illuminate\Database\Schema\Builder
- */
-class Schema extends Facade
-{
- /**
- * Get a schema builder instance for a connection.
- *
- * @param string $name
- * @return \Illuminate\Database\Schema\Builder
- */
- public static function connection($name)
- {
- return static::$app['db']->connection($name)->getSchemaBuilder();
- }
-
- /**
- * Get a schema builder instance for the default connection.
- *
- * @return \Illuminate\Database\Schema\Builder
- */
- protected static function getFacadeAccessor()
- {
- return static::$app['db']->connection()->getSchemaBuilder();
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static string getName()
- * @method static string getId()
- * @method static void setId(string $id)
- * @method static bool start()
- * @method static bool save()
- * @method static array all()
- * @method static bool exists(string|array $key)
- * @method static bool has(string|array $key)
- * @method static mixed get(string $key, $default = null)
- * @method static mixed pull(string $key, $default = null)
- * @method static void put(string|array $key, $value = null)
- * @method static string token()
- * @method static mixed remove(string $key)
- * @method static void forget(string|array $keys)
- * @method static void flush()
- * @method static bool migrate(bool $destroy = false)
- * @method static bool isStarted()
- * @method static string|null previousUrl()
- * @method static void setPreviousUrl(string $url)
- * @method static \SessionHandlerInterface getHandler()
- * @method static bool handlerNeedsRequest()
- * @method static void setRequestOnHandler(\Illuminate\Http\Request $request)
- *
- * @see \Illuminate\Session\SessionManager
- * @see \Illuminate\Session\Store
- */
-class Session extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'session';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-use Illuminate\Filesystem\Filesystem;
-
-/**
- * @method static \Illuminate\Contracts\Filesystem\Filesystem disk(string $name = null)
- *
- * @see \Illuminate\Filesystem\FilesystemManager
- */
-class Storage extends Facade
-{
- /**
- * Replace the given disk with a local testing disk.
- *
- * @param string|null $disk
- *
- * @return \Illuminate\Filesystem\Filesystem
- */
- public static function fake($disk = null)
- {
- $disk = $disk ?: self::$app['config']->get('filesystems.default');
-
- (new Filesystem)->cleanDirectory(
- $root = storage_path('framework/testing/disks/'.$disk)
- );
-
- static::set($disk, $fake = self::createLocalDriver(['root' => $root]));
-
- return $fake;
- }
-
- /**
- * Replace the given disk with a persistent local testing disk.
- *
- * @param string|null $disk
- * @return \Illuminate\Filesystem\Filesystem
- */
- public static function persistentFake($disk = null)
- {
- $disk = $disk ?: self::$app['config']->get('filesystems.default');
-
- static::set($disk, $fake = self::createLocalDriver([
- 'root' => storage_path('framework/testing/disks/'.$disk),
- ]));
-
- return $fake;
- }
-
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'filesystem';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static string current()
- * @method static string full()
- * @method static string previous($fallback = false)
- * @method static string to(string $path, $extra = [], bool $secure = null)
- * @method static string secure(string $path, array $parameters = [])
- * @method static string asset(string $path, bool $secure = null)
- * @method static string route(string $name, $parameters = [], bool $absolute = true)
- * @method static string action(string $action, $parameters = [], bool $absolute = true)
- * @method static \Illuminate\Contracts\Routing\UrlGenerator setRootControllerNamespace(string $rootNamespace)
- * @method static string signedRoute(string $name, array $parameters = [], \DateTimeInterface|\DateInterval|int $expiration = null, bool $absolute = true)
- * @method static string temporarySignedRoute(string $name, \DateTimeInterface|\DateInterval|int $expiration, array $parameters = [], bool $absolute = true)
- * @method static string hasValidSignature(\Illuminate\Http\Request $request, bool $absolute = true)
- * @method static void defaults(array $defaults)
- *
- * @see \Illuminate\Routing\UrlGenerator
- */
-class URL extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'url';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static \Illuminate\Contracts\Validation\Validator make(array $data, array $rules, array $messages = [], array $customAttributes = [])
- * @method static void extend(string $rule, \Closure|string $extension, string $message = null)
- * @method static void extendImplicit(string $rule, \Closure|string $extension, string $message = null)
- * @method static void replacer(string $rule, \Closure|string $replacer)
- *
- * @see \Illuminate\Validation\Factory
- */
-class Validator extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'validator';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Facades;
-
-/**
- * @method static bool exists(string $view)
- * @method static \Illuminate\Contracts\View\View file(string $path, array $data = [], array $mergeData = [])
- * @method static \Illuminate\Contracts\View\View make(string $view, array $data = [], array $mergeData = [])
- * @method static mixed share(array|string $key, $value = null)
- * @method static array composer(array|string $views, \Closure|string $callback)
- * @method static array creator(array|string $views, \Closure|string $callback)
- * @method static \Illuminate\Contracts\View\Factory addNamespace(string $namespace, string|array $hints)
- * @method static \Illuminate\Contracts\View\Factory replaceNamespace(string $namespace, string|array $hints)
- *
- * @see \Illuminate\View\Factory
- */
-class View extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor()
- {
- return 'view';
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use ArrayAccess;
-use JsonSerializable;
-use Illuminate\Contracts\Support\Jsonable;
-use Illuminate\Contracts\Support\Arrayable;
-
-class Fluent implements ArrayAccess, Arrayable, Jsonable, JsonSerializable
-{
- /**
- * All of the attributes set on the fluent instance.
- *
- * @var array
- */
- protected $attributes = [];
-
- /**
- * Create a new fluent instance.
- *
- * @param array|object $attributes
- * @return void
- */
- public function __construct($attributes = [])
- {
- foreach ($attributes as $key => $value) {
- $this->attributes[$key] = $value;
- }
- }
-
- /**
- * Get an attribute from the fluent instance.
- *
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- public function get($key, $default = null)
- {
- if (array_key_exists($key, $this->attributes)) {
- return $this->attributes[$key];
- }
-
- return value($default);
- }
-
- /**
- * Get the attributes from the fluent instance.
- *
- * @return array
- */
- public function getAttributes()
- {
- return $this->attributes;
- }
-
- /**
- * Convert the fluent instance to an array.
- *
- * @return array
- */
- public function toArray()
- {
- return $this->attributes;
- }
-
- /**
- * Convert the object into something JSON serializable.
- *
- * @return array
- */
- public function jsonSerialize()
- {
- return $this->toArray();
- }
-
- /**
- * Convert the fluent instance to JSON.
- *
- * @param int $options
- * @return string
- */
- public function toJson($options = 0)
- {
- return json_encode($this->jsonSerialize(), $options);
- }
-
- /**
- * Determine if the given offset exists.
- *
- * @param string $offset
- * @return bool
- */
- public function offsetExists($offset)
- {
- return isset($this->attributes[$offset]);
- }
-
- /**
- * Get the value for a given offset.
- *
- * @param string $offset
- * @return mixed
- */
- public function offsetGet($offset)
- {
- return $this->get($offset);
- }
-
- /**
- * Set the value at the given offset.
- *
- * @param string $offset
- * @param mixed $value
- * @return void
- */
- public function offsetSet($offset, $value)
- {
- $this->attributes[$offset] = $value;
- }
-
- /**
- * Unset the value at the given offset.
- *
- * @param string $offset
- * @return void
- */
- public function offsetUnset($offset)
- {
- unset($this->attributes[$offset]);
- }
-
- /**
- * Handle dynamic calls to the fluent instance to set attributes.
- *
- * @param string $method
- * @param array $parameters
- * @return $this
- */
- public function __call($method, $parameters)
- {
- $this->attributes[$method] = count($parameters) > 0 ? $parameters[0] : true;
-
- return $this;
- }
-
- /**
- * Dynamically retrieve the value of an attribute.
- *
- * @param string $key
- * @return mixed
- */
- public function __get($key)
- {
- return $this->get($key);
- }
-
- /**
- * Dynamically set the value of an attribute.
- *
- * @param string $key
- * @param mixed $value
- * @return void
- */
- public function __set($key, $value)
- {
- $this->offsetSet($key, $value);
- }
-
- /**
- * Dynamically check if an attribute is set.
- *
- * @param string $key
- * @return bool
- */
- public function __isset($key)
- {
- return $this->offsetExists($key);
- }
-
- /**
- * Dynamically unset an attribute.
- *
- * @param string $key
- * @return void
- */
- public function __unset($key)
- {
- $this->offsetUnset($key);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-/**
- * @mixin \Illuminate\Support\Collection
- */
-class HigherOrderCollectionProxy
-{
- /**
- * The collection being operated on.
- *
- * @var \Illuminate\Support\Collection
- */
- protected $collection;
-
- /**
- * The method being proxied.
- *
- * @var string
- */
- protected $method;
-
- /**
- * Create a new proxy instance.
- *
- * @param \Illuminate\Support\Collection $collection
- * @param string $method
- * @return void
- */
- public function __construct(Collection $collection, $method)
- {
- $this->method = $method;
- $this->collection = $collection;
- }
-
- /**
- * Proxy accessing an attribute onto the collection items.
- *
- * @param string $key
- * @return mixed
- */
- public function __get($key)
- {
- return $this->collection->{$this->method}(function ($value) use ($key) {
- return is_array($value) ? $value[$key] : $value->{$key};
- });
- }
-
- /**
- * Proxy a method call onto the collection items.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
- return $value->{$method}(...$parameters);
- });
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-class HigherOrderTapProxy
-{
- /**
- * The target being tapped.
- *
- * @var mixed
- */
- public $target;
-
- /**
- * Create a new tap proxy instance.
- *
- * @param mixed $target
- * @return void
- */
- public function __construct($target)
- {
- $this->target = $target;
- }
-
- /**
- * Dynamically pass method calls to the target.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- $this->target->{$method}(...$parameters);
-
- return $this->target;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Illuminate\Contracts\Support\Htmlable;
-
-class HtmlString implements Htmlable
-{
- /**
- * The HTML string.
- *
- * @var string
- */
- protected $html;
-
- /**
- * Create a new HTML string instance.
- *
- * @param string $html
- * @return void
- */
- public function __construct($html)
- {
- $this->html = $html;
- }
-
- /**
- * Get the HTML string.
- *
- * @return string
- */
- public function toHtml()
- {
- return $this->html;
- }
-
- /**
- * Get the HTML string.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->toHtml();
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use DateInterval;
-use DateTimeInterface;
-
-trait InteractsWithTime
-{
- /**
- * Get the number of seconds until the given DateTime.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @return int
- */
- protected function secondsUntil($delay)
- {
- $delay = $this->parseDateInterval($delay);
-
- return $delay instanceof DateTimeInterface
- ? max(0, $delay->getTimestamp() - $this->currentTime())
- : (int) $delay;
- }
-
- /**
- * Get the "available at" UNIX timestamp.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @return int
- */
- protected function availableAt($delay = 0)
- {
- $delay = $this->parseDateInterval($delay);
-
- return $delay instanceof DateTimeInterface
- ? $delay->getTimestamp()
- : Carbon::now()->addRealSeconds($delay)->getTimestamp();
- }
-
- /**
- * If the given value is an interval, convert it to a DateTime instance.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @return \DateTimeInterface|int
- */
- protected function parseDateInterval($delay)
- {
- if ($delay instanceof DateInterval) {
- $delay = Carbon::now()->add($delay);
- }
-
- return $delay;
- }
-
- /**
- * Get the current system time as a UNIX timestamp.
- *
- * @return int
- */
- protected function currentTime()
- {
- return Carbon::now()->getTimestamp();
- }
-}
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) Taylor Otwell
-
-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.
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Closure;
-use InvalidArgumentException;
-
-abstract class Manager
-{
- /**
- * The application instance.
- *
- * @var \Illuminate\Contracts\Foundation\Application
- */
- protected $app;
-
- /**
- * The registered custom driver creators.
- *
- * @var array
- */
- protected $customCreators = [];
-
- /**
- * The array of created "drivers".
- *
- * @var array
- */
- protected $drivers = [];
-
- /**
- * Create a new manager instance.
- *
- * @param \Illuminate\Contracts\Foundation\Application $app
- * @return void
- */
- public function __construct($app)
- {
- $this->app = $app;
- }
-
- /**
- * Get the default driver name.
- *
- * @return string
- */
- abstract public function getDefaultDriver();
-
- /**
- * Get a driver instance.
- *
- * @param string $driver
- * @return mixed
- *
- * @throws \InvalidArgumentException
- */
- public function driver($driver = null)
- {
- $driver = $driver ?: $this->getDefaultDriver();
-
- if (is_null($driver)) {
- throw new InvalidArgumentException(sprintf(
- 'Unable to resolve NULL driver for [%s].', static::class
- ));
- }
-
- // If the given driver has not been created before, we will create the instances
- // here and cache it so we can return it next time very quickly. If there is
- // already a driver created by this name, we'll just return that instance.
- if (! isset($this->drivers[$driver])) {
- $this->drivers[$driver] = $this->createDriver($driver);
- }
-
- return $this->drivers[$driver];
- }
-
- /**
- * Create a new driver instance.
- *
- * @param string $driver
- * @return mixed
- *
- * @throws \InvalidArgumentException
- */
- protected function createDriver($driver)
- {
- // First, we will determine if a custom driver creator exists for the given driver and
- // if it does not we will check for a creator method for the driver. Custom creator
- // callbacks allow developers to build their own "drivers" easily using Closures.
- if (isset($this->customCreators[$driver])) {
- return $this->callCustomCreator($driver);
- } else {
- $method = 'create'.Str::studly($driver).'Driver';
-
- if (method_exists($this, $method)) {
- return $this->$method();
- }
- }
- throw new InvalidArgumentException("Driver [$driver] not supported.");
- }
-
- /**
- * Call a custom driver creator.
- *
- * @param string $driver
- * @return mixed
- */
- protected function callCustomCreator($driver)
- {
- return $this->customCreators[$driver]($this->app);
- }
-
- /**
- * Register a custom driver creator Closure.
- *
- * @param string $driver
- * @param \Closure $callback
- * @return $this
- */
- public function extend($driver, Closure $callback)
- {
- $this->customCreators[$driver] = $callback;
-
- return $this;
- }
-
- /**
- * Get all of the created "drivers".
- *
- * @return array
- */
- public function getDrivers()
- {
- return $this->drivers;
- }
-
- /**
- * Dynamically call the default driver instance.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- return $this->driver()->$method(...$parameters);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Countable;
-use JsonSerializable;
-use Illuminate\Contracts\Support\Jsonable;
-use Illuminate\Contracts\Support\Arrayable;
-use Illuminate\Contracts\Support\MessageProvider;
-use Illuminate\Contracts\Support\MessageBag as MessageBagContract;
-
-class MessageBag implements Arrayable, Countable, Jsonable, JsonSerializable, MessageBagContract, MessageProvider
-{
- /**
- * All of the registered messages.
- *
- * @var array
- */
- protected $messages = [];
-
- /**
- * Default format for message output.
- *
- * @var string
- */
- protected $format = ':message';
-
- /**
- * Create a new message bag instance.
- *
- * @param array $messages
- * @return void
- */
- public function __construct(array $messages = [])
- {
- foreach ($messages as $key => $value) {
- $value = $value instanceof Arrayable ? $value->toArray() : (array) $value;
-
- $this->messages[$key] = array_unique($value);
- }
- }
-
- /**
- * Get the keys present in the message bag.
- *
- * @return array
- */
- public function keys()
- {
- return array_keys($this->messages);
- }
-
- /**
- * Add a message to the message bag.
- *
- * @param string $key
- * @param string $message
- * @return $this
- */
- public function add($key, $message)
- {
- if ($this->isUnique($key, $message)) {
- $this->messages[$key][] = $message;
- }
-
- return $this;
- }
-
- /**
- * Determine if a key and message combination already exists.
- *
- * @param string $key
- * @param string $message
- * @return bool
- */
- protected function isUnique($key, $message)
- {
- $messages = (array) $this->messages;
-
- return ! isset($messages[$key]) || ! in_array($message, $messages[$key]);
- }
-
- /**
- * Merge a new array of messages into the message bag.
- *
- * @param \Illuminate\Contracts\Support\MessageProvider|array $messages
- * @return $this
- */
- public function merge($messages)
- {
- if ($messages instanceof MessageProvider) {
- $messages = $messages->getMessageBag()->getMessages();
- }
-
- $this->messages = array_merge_recursive($this->messages, $messages);
-
- return $this;
- }
-
- /**
- * Determine if messages exist for all of the given keys.
- *
- * @param array|string $key
- * @return bool
- */
- public function has($key)
- {
- if ($this->isEmpty()) {
- return false;
- }
-
- if (is_null($key)) {
- return $this->any();
- }
-
- $keys = is_array($key) ? $key : func_get_args();
-
- foreach ($keys as $key) {
- if ($this->first($key) === '') {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Determine if messages exist for any of the given keys.
- *
- * @param array|string $keys
- * @return bool
- */
- public function hasAny($keys = [])
- {
- if ($this->isEmpty()) {
- return false;
- }
-
- $keys = is_array($keys) ? $keys : func_get_args();
-
- foreach ($keys as $key) {
- if ($this->has($key)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Get the first message from the message bag for a given key.
- *
- * @param string $key
- * @param string $format
- * @return string
- */
- public function first($key = null, $format = null)
- {
- $messages = is_null($key) ? $this->all($format) : $this->get($key, $format);
-
- $firstMessage = Arr::first($messages, null, '');
-
- return is_array($firstMessage) ? Arr::first($firstMessage) : $firstMessage;
- }
-
- /**
- * Get all of the messages from the message bag for a given key.
- *
- * @param string $key
- * @param string $format
- * @return array
- */
- public function get($key, $format = null)
- {
- // If the message exists in the message bag, we will transform it and return
- // the message. Otherwise, we will check if the key is implicit & collect
- // all the messages that match the given key and output it as an array.
- if (array_key_exists($key, $this->messages)) {
- return $this->transform(
- $this->messages[$key], $this->checkFormat($format), $key
- );
- }
-
- if (Str::contains($key, '*')) {
- return $this->getMessagesForWildcardKey($key, $format);
- }
-
- return [];
- }
-
- /**
- * Get the messages for a wildcard key.
- *
- * @param string $key
- * @param string|null $format
- * @return array
- */
- protected function getMessagesForWildcardKey($key, $format)
- {
- return collect($this->messages)
- ->filter(function ($messages, $messageKey) use ($key) {
- return Str::is($key, $messageKey);
- })
- ->map(function ($messages, $messageKey) use ($format) {
- return $this->transform(
- $messages, $this->checkFormat($format), $messageKey
- );
- })->all();
- }
-
- /**
- * Get all of the messages for every key in the message bag.
- *
- * @param string $format
- * @return array
- */
- public function all($format = null)
- {
- $format = $this->checkFormat($format);
-
- $all = [];
-
- foreach ($this->messages as $key => $messages) {
- $all = array_merge($all, $this->transform($messages, $format, $key));
- }
-
- return $all;
- }
-
- /**
- * Get all of the unique messages for every key in the message bag.
- *
- * @param string $format
- * @return array
- */
- public function unique($format = null)
- {
- return array_unique($this->all($format));
- }
-
- /**
- * Format an array of messages.
- *
- * @param array $messages
- * @param string $format
- * @param string $messageKey
- * @return array
- */
- protected function transform($messages, $format, $messageKey)
- {
- return collect((array) $messages)
- ->map(function ($message) use ($format, $messageKey) {
- // We will simply spin through the given messages and transform each one
- // replacing the :message place holder with the real message allowing
- // the messages to be easily formatted to each developer's desires.
- return str_replace([':message', ':key'], [$message, $messageKey], $format);
- })->all();
- }
-
- /**
- * Get the appropriate format based on the given format.
- *
- * @param string $format
- * @return string
- */
- protected function checkFormat($format)
- {
- return $format ?: $this->format;
- }
-
- /**
- * Get the raw messages in the message bag.
- *
- * @return array
- */
- public function messages()
- {
- return $this->messages;
- }
-
- /**
- * Get the raw messages in the message bag.
- *
- * @return array
- */
- public function getMessages()
- {
- return $this->messages();
- }
-
- /**
- * Get the messages for the instance.
- *
- * @return \Illuminate\Support\MessageBag
- */
- public function getMessageBag()
- {
- return $this;
- }
-
- /**
- * Get the default message format.
- *
- * @return string
- */
- public function getFormat()
- {
- return $this->format;
- }
-
- /**
- * Set the default message format.
- *
- * @param string $format
- * @return \Illuminate\Support\MessageBag
- */
- public function setFormat($format = ':message')
- {
- $this->format = $format;
-
- return $this;
- }
-
- /**
- * Determine if the message bag has any messages.
- *
- * @return bool
- */
- public function isEmpty()
- {
- return ! $this->any();
- }
-
- /**
- * Determine if the message bag has any messages.
- *
- * @return bool
- */
- public function isNotEmpty()
- {
- return $this->any();
- }
-
- /**
- * Determine if the message bag has any messages.
- *
- * @return bool
- */
- public function any()
- {
- return $this->count() > 0;
- }
-
- /**
- * Get the number of messages in the message bag.
- *
- * @return int
- */
- public function count()
- {
- return count($this->messages, COUNT_RECURSIVE) - count($this->messages);
- }
-
- /**
- * Get the instance as an array.
- *
- * @return array
- */
- public function toArray()
- {
- return $this->getMessages();
- }
-
- /**
- * Convert the object into something JSON serializable.
- *
- * @return array
- */
- public function jsonSerialize()
- {
- return $this->toArray();
- }
-
- /**
- * Convert the object to its JSON representation.
- *
- * @param int $options
- * @return string
- */
- public function toJson($options = 0)
- {
- return json_encode($this->jsonSerialize(), $options);
- }
-
- /**
- * Convert the message bag to its string representation.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->toJson();
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-class NamespacedItemResolver
-{
- /**
- * A cache of the parsed items.
- *
- * @var array
- */
- protected $parsed = [];
-
- /**
- * Parse a key into namespace, group, and item.
- *
- * @param string $key
- * @return array
- */
- public function parseKey($key)
- {
- // If we've already parsed the given key, we'll return the cached version we
- // already have, as this will save us some processing. We cache off every
- // key we parse so we can quickly return it on all subsequent requests.
- if (isset($this->parsed[$key])) {
- return $this->parsed[$key];
- }
-
- // If the key does not contain a double colon, it means the key is not in a
- // namespace, and is just a regular configuration item. Namespaces are a
- // tool for organizing configuration items for things such as modules.
- if (strpos($key, '::') === false) {
- $segments = explode('.', $key);
-
- $parsed = $this->parseBasicSegments($segments);
- } else {
- $parsed = $this->parseNamespacedSegments($key);
- }
-
- // Once we have the parsed array of this key's elements, such as its groups
- // and namespace, we will cache each array inside a simple list that has
- // the key and the parsed array for quick look-ups for later requests.
- return $this->parsed[$key] = $parsed;
- }
-
- /**
- * Parse an array of basic segments.
- *
- * @param array $segments
- * @return array
- */
- protected function parseBasicSegments(array $segments)
- {
- // The first segment in a basic array will always be the group, so we can go
- // ahead and grab that segment. If there is only one total segment we are
- // just pulling an entire group out of the array and not a single item.
- $group = $segments[0];
-
- // If there is more than one segment in this group, it means we are pulling
- // a specific item out of a group and will need to return this item name
- // as well as the group so we know which item to pull from the arrays.
- $item = count($segments) === 1
- ? null
- : implode('.', array_slice($segments, 1));
-
- return [null, $group, $item];
- }
-
- /**
- * Parse an array of namespaced segments.
- *
- * @param string $key
- * @return array
- */
- protected function parseNamespacedSegments($key)
- {
- [$namespace, $item] = explode('::', $key);
-
- // First we'll just explode the first segment to get the namespace and group
- // since the item should be in the remaining segments. Once we have these
- // two pieces of data we can proceed with parsing out the item's value.
- $itemSegments = explode('.', $item);
-
- $groupAndItem = array_slice(
- $this->parseBasicSegments($itemSegments), 1
- );
-
- return array_merge([$namespace], $groupAndItem);
- }
-
- /**
- * Set the parsed value of a key.
- *
- * @param string $key
- * @param array $parsed
- * @return void
- */
- public function setParsedKey($key, $parsed)
- {
- $this->parsed[$key] = $parsed;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use ArrayAccess;
-use ArrayObject;
-
-class Optional implements ArrayAccess
-{
- use Traits\Macroable {
- __call as macroCall;
- }
-
- /**
- * The underlying object.
- *
- * @var mixed
- */
- protected $value;
-
- /**
- * Create a new optional instance.
- *
- * @param mixed $value
- * @return void
- */
- public function __construct($value)
- {
- $this->value = $value;
- }
-
- /**
- * Dynamically access a property on the underlying object.
- *
- * @param string $key
- * @return mixed
- */
- public function __get($key)
- {
- if (is_object($this->value)) {
- return $this->value->{$key} ?? null;
- }
- }
-
- /**
- * Dynamically check a property exists on the underlying object.
- *
- * @param mixed $name
- * @return bool
- */
- public function __isset($name)
- {
- if (is_object($this->value)) {
- return isset($this->value->{$name});
- }
-
- if (is_array($this->value) || $this->value instanceof ArrayObject) {
- return isset($this->value[$name]);
- }
-
- return false;
- }
-
- /**
- * Determine if an item exists at an offset.
- *
- * @param mixed $key
- * @return bool
- */
- public function offsetExists($key)
- {
- return Arr::accessible($this->value) && Arr::exists($this->value, $key);
- }
-
- /**
- * Get an item at a given offset.
- *
- * @param mixed $key
- * @return mixed
- */
- public function offsetGet($key)
- {
- return Arr::get($this->value, $key);
- }
-
- /**
- * Set the item at a given offset.
- *
- * @param mixed $key
- * @param mixed $value
- * @return void
- */
- public function offsetSet($key, $value)
- {
- if (Arr::accessible($this->value)) {
- $this->value[$key] = $value;
- }
- }
-
- /**
- * Unset the item at a given offset.
- *
- * @param string $key
- * @return void
- */
- public function offsetUnset($key)
- {
- if (Arr::accessible($this->value)) {
- unset($this->value[$key]);
- }
- }
-
- /**
- * Dynamically pass a method to the underlying object.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- if (static::hasMacro($method)) {
- return $this->macroCall($method, $parameters);
- }
-
- if (is_object($this->value)) {
- return $this->value->{$method}(...$parameters);
- }
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Doctrine\Common\Inflector\Inflector;
-
-class Pluralizer
-{
- /**
- * Uncountable word forms.
- *
- * @var array
- */
- public static $uncountable = [
- 'audio',
- 'bison',
- 'cattle',
- 'chassis',
- 'compensation',
- 'coreopsis',
- 'data',
- 'deer',
- 'education',
- 'emoji',
- 'equipment',
- 'evidence',
- 'feedback',
- 'firmware',
- 'fish',
- 'furniture',
- 'gold',
- 'hardware',
- 'information',
- 'jedi',
- 'kin',
- 'knowledge',
- 'love',
- 'metadata',
- 'money',
- 'moose',
- 'news',
- 'nutrition',
- 'offspring',
- 'plankton',
- 'pokemon',
- 'police',
- 'rain',
- 'recommended',
- 'related',
- 'rice',
- 'series',
- 'sheep',
- 'software',
- 'species',
- 'swine',
- 'traffic',
- 'wheat',
- ];
-
- /**
- * Get the plural form of an English word.
- *
- * @param string $value
- * @param int $count
- * @return string
- */
- public static function plural($value, $count = 2)
- {
- if ((int) abs($count) === 1 || static::uncountable($value)) {
- return $value;
- }
-
- $plural = Inflector::pluralize($value);
-
- return static::matchCase($plural, $value);
- }
-
- /**
- * Get the singular form of an English word.
- *
- * @param string $value
- * @return string
- */
- public static function singular($value)
- {
- $singular = Inflector::singularize($value);
-
- return static::matchCase($singular, $value);
- }
-
- /**
- * Determine if the given value is uncountable.
- *
- * @param string $value
- * @return bool
- */
- protected static function uncountable($value)
- {
- return in_array(strtolower($value), static::$uncountable);
- }
-
- /**
- * Attempt to match the case on two strings.
- *
- * @param string $value
- * @param string $comparison
- * @return string
- */
- protected static function matchCase($value, $comparison)
- {
- $functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords'];
-
- foreach ($functions as $function) {
- if (call_user_func($function, $comparison) === $comparison) {
- return call_user_func($function, $value);
- }
- }
-
- return $value;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-/**
- * ProcessUtils is a bunch of utility methods.
- *
- * This class was originally copied from Symfony 3.
- */
-class ProcessUtils
-{
- /**
- * Escapes a string to be used as a shell argument.
- *
- * @param string $argument
- * @return string
- */
- public static function escapeArgument($argument)
- {
- // Fix for PHP bug #43784 escapeshellarg removes % from given string
- // Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
- // @see https://bugs.php.net/bug.php?id=43784
- // @see https://bugs.php.net/bug.php?id=49446
- if ('\\' === DIRECTORY_SEPARATOR) {
- if ('' === $argument) {
- return '""';
- }
-
- $escapedArgument = '';
- $quote = false;
-
- foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
- if ('"' === $part) {
- $escapedArgument .= '\\"';
- } elseif (self::isSurroundedBy($part, '%')) {
- // Avoid environment variable expansion
- $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
- } else {
- // escape trailing backslash
- if ('\\' === substr($part, -1)) {
- $part .= '\\';
- }
- $quote = true;
- $escapedArgument .= $part;
- }
- }
-
- if ($quote) {
- $escapedArgument = '"'.$escapedArgument.'"';
- }
-
- return $escapedArgument;
- }
-
- return "'".str_replace("'", "'\\''", $argument)."'";
- }
-
- /**
- * Is the given string surrounded by the given character?
- *
- * @param string $arg
- * @param string $char
- * @return bool
- */
- protected static function isSurroundedBy($arg, $char)
- {
- return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Illuminate\Console\Application as Artisan;
-use Illuminate\Contracts\Support\DeferrableProvider;
-
-abstract class ServiceProvider
-{
- /**
- * The application instance.
- *
- * @var \Illuminate\Contracts\Foundation\Application
- */
- protected $app;
-
- /**
- * Indicates if loading of the provider is deferred.
- *
- * @deprecated Implement the \Illuminate\Contracts\Support\DeferrableProvider interface instead. Will be removed in Laravel 5.9.
- *
- * @var bool
- */
- protected $defer = false;
-
- /**
- * The paths that should be published.
- *
- * @var array
- */
- public static $publishes = [];
-
- /**
- * The paths that should be published by group.
- *
- * @var array
- */
- public static $publishGroups = [];
-
- /**
- * Create a new service provider instance.
- *
- * @param \Illuminate\Contracts\Foundation\Application $app
- * @return void
- */
- public function __construct($app)
- {
- $this->app = $app;
- }
-
- /**
- * Register any application services.
- *
- * @return void
- */
- public function register()
- {
- //
- }
-
- /**
- * Merge the given configuration with the existing configuration.
- *
- * @param string $path
- * @param string $key
- * @return void
- */
- protected function mergeConfigFrom($path, $key)
- {
- $config = $this->app['config']->get($key, []);
-
- $this->app['config']->set($key, array_merge(require $path, $config));
- }
-
- /**
- * Load the given routes file if routes are not already cached.
- *
- * @param string $path
- * @return void
- */
- protected function loadRoutesFrom($path)
- {
- if (! $this->app->routesAreCached()) {
- require $path;
- }
- }
-
- /**
- * Register a view file namespace.
- *
- * @param string|array $path
- * @param string $namespace
- * @return void
- */
- protected function loadViewsFrom($path, $namespace)
- {
- if (is_array($this->app->config['view']['paths'])) {
- foreach ($this->app->config['view']['paths'] as $viewPath) {
- if (is_dir($appPath = $viewPath.'/vendor/'.$namespace)) {
- $this->app['view']->addNamespace($namespace, $appPath);
- }
- }
- }
-
- $this->app['view']->addNamespace($namespace, $path);
- }
-
- /**
- * Register a translation file namespace.
- *
- * @param string $path
- * @param string $namespace
- * @return void
- */
- protected function loadTranslationsFrom($path, $namespace)
- {
- $this->app['translator']->addNamespace($namespace, $path);
- }
-
- /**
- * Register a JSON translation file path.
- *
- * @param string $path
- * @return void
- */
- protected function loadJsonTranslationsFrom($path)
- {
- $this->app['translator']->addJsonPath($path);
- }
-
- /**
- * Register a database migration path.
- *
- * @param array|string $paths
- * @return void
- */
- protected function loadMigrationsFrom($paths)
- {
- $this->app->afterResolving('migrator', function ($migrator) use ($paths) {
- foreach ((array) $paths as $path) {
- $migrator->path($path);
- }
- });
- }
-
- /**
- * Register paths to be published by the publish command.
- *
- * @param array $paths
- * @param mixed $groups
- * @return void
- */
- protected function publishes(array $paths, $groups = null)
- {
- $this->ensurePublishArrayInitialized($class = static::class);
-
- static::$publishes[$class] = array_merge(static::$publishes[$class], $paths);
-
- if (! is_null($groups)) {
- foreach ((array) $groups as $group) {
- $this->addPublishGroup($group, $paths);
- }
- }
- }
-
- /**
- * Ensure the publish array for the service provider is initialized.
- *
- * @param string $class
- * @return void
- */
- protected function ensurePublishArrayInitialized($class)
- {
- if (! array_key_exists($class, static::$publishes)) {
- static::$publishes[$class] = [];
- }
- }
-
- /**
- * Add a publish group / tag to the service provider.
- *
- * @param string $group
- * @param array $paths
- * @return void
- */
- protected function addPublishGroup($group, $paths)
- {
- if (! array_key_exists($group, static::$publishGroups)) {
- static::$publishGroups[$group] = [];
- }
-
- static::$publishGroups[$group] = array_merge(
- static::$publishGroups[$group], $paths
- );
- }
-
- /**
- * Get the paths to publish.
- *
- * @param string $provider
- * @param string $group
- * @return array
- */
- public static function pathsToPublish($provider = null, $group = null)
- {
- if (! is_null($paths = static::pathsForProviderOrGroup($provider, $group))) {
- return $paths;
- }
-
- return collect(static::$publishes)->reduce(function ($paths, $p) {
- return array_merge($paths, $p);
- }, []);
- }
-
- /**
- * Get the paths for the provider or group (or both).
- *
- * @param string|null $provider
- * @param string|null $group
- * @return array
- */
- protected static function pathsForProviderOrGroup($provider, $group)
- {
- if ($provider && $group) {
- return static::pathsForProviderAndGroup($provider, $group);
- } elseif ($group && array_key_exists($group, static::$publishGroups)) {
- return static::$publishGroups[$group];
- } elseif ($provider && array_key_exists($provider, static::$publishes)) {
- return static::$publishes[$provider];
- } elseif ($group || $provider) {
- return [];
- }
- }
-
- /**
- * Get the paths for the provider and group.
- *
- * @param string $provider
- * @param string $group
- * @return array
- */
- protected static function pathsForProviderAndGroup($provider, $group)
- {
- if (! empty(static::$publishes[$provider]) && ! empty(static::$publishGroups[$group])) {
- return array_intersect_key(static::$publishes[$provider], static::$publishGroups[$group]);
- }
-
- return [];
- }
-
- /**
- * Get the service providers available for publishing.
- *
- * @return array
- */
- public static function publishableProviders()
- {
- return array_keys(static::$publishes);
- }
-
- /**
- * Get the groups available for publishing.
- *
- * @return array
- */
- public static function publishableGroups()
- {
- return array_keys(static::$publishGroups);
- }
-
- /**
- * Register the package's custom Artisan commands.
- *
- * @param array|mixed $commands
- * @return void
- */
- public function commands($commands)
- {
- $commands = is_array($commands) ? $commands : func_get_args();
-
- Artisan::starting(function ($artisan) use ($commands) {
- $artisan->resolveCommands($commands);
- });
- }
-
- /**
- * Get the services provided by the provider.
- *
- * @return array
- */
- public function provides()
- {
- return [];
- }
-
- /**
- * Get the events that trigger this service provider to register.
- *
- * @return array
- */
- public function when()
- {
- return [];
- }
-
- /**
- * Determine if the provider is deferred.
- *
- * @return bool
- */
- public function isDeferred()
- {
- return $this->defer || $this instanceof DeferrableProvider;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Ramsey\Uuid\Uuid;
-use Ramsey\Uuid\UuidFactory;
-use Illuminate\Support\Traits\Macroable;
-use Ramsey\Uuid\Generator\CombGenerator;
-use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
-
-class Str
-{
- use Macroable;
-
- /**
- * The cache of snake-cased words.
- *
- * @var array
- */
- protected static $snakeCache = [];
-
- /**
- * The cache of camel-cased words.
- *
- * @var array
- */
- protected static $camelCache = [];
-
- /**
- * The cache of studly-cased words.
- *
- * @var array
- */
- protected static $studlyCache = [];
-
- /**
- * Return the remainder of a string after a given value.
- *
- * @param string $subject
- * @param string $search
- * @return string
- */
- public static function after($subject, $search)
- {
- return $search === '' ? $subject : array_reverse(explode($search, $subject, 2))[0];
- }
-
- /**
- * Transliterate a UTF-8 value to ASCII.
- *
- * @param string $value
- * @param string $language
- * @return string
- */
- public static function ascii($value, $language = 'en')
- {
- $languageSpecific = static::languageSpecificCharsArray($language);
-
- if (! is_null($languageSpecific)) {
- $value = str_replace($languageSpecific[0], $languageSpecific[1], $value);
- }
-
- foreach (static::charsArray() as $key => $val) {
- $value = str_replace($val, $key, $value);
- }
-
- return preg_replace('/[^\x20-\x7E]/u', '', $value);
- }
-
- /**
- * Get the portion of a string before a given value.
- *
- * @param string $subject
- * @param string $search
- * @return string
- */
- public static function before($subject, $search)
- {
- return $search === '' ? $subject : explode($search, $subject)[0];
- }
-
- /**
- * Convert a value to camel case.
- *
- * @param string $value
- * @return string
- */
- public static function camel($value)
- {
- if (isset(static::$camelCache[$value])) {
- return static::$camelCache[$value];
- }
-
- return static::$camelCache[$value] = lcfirst(static::studly($value));
- }
-
- /**
- * Determine if a given string contains a given substring.
- *
- * @param string $haystack
- * @param string|array $needles
- * @return bool
- */
- public static function contains($haystack, $needles)
- {
- foreach ((array) $needles as $needle) {
- if ($needle !== '' && mb_strpos($haystack, $needle) !== false) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Determine if a given string contains all array values.
- *
- * @param string $haystack
- * @param array $needles
- * @return bool
- */
- public static function containsAll($haystack, array $needles)
- {
- foreach ($needles as $needle) {
- if (! static::contains($haystack, $needle)) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Determine if a given string ends with a given substring.
- *
- * @param string $haystack
- * @param string|array $needles
- * @return bool
- */
- public static function endsWith($haystack, $needles)
- {
- foreach ((array) $needles as $needle) {
- if (substr($haystack, -strlen($needle)) === (string) $needle) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Cap a string with a single instance of a given value.
- *
- * @param string $value
- * @param string $cap
- * @return string
- */
- public static function finish($value, $cap)
- {
- $quoted = preg_quote($cap, '/');
-
- return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
- }
-
- /**
- * Determine if a given string matches a given pattern.
- *
- * @param string|array $pattern
- * @param string $value
- * @return bool
- */
- public static function is($pattern, $value)
- {
- $patterns = Arr::wrap($pattern);
-
- if (empty($patterns)) {
- return false;
- }
-
- foreach ($patterns as $pattern) {
- // If the given value is an exact match we can of course return true right
- // from the beginning. Otherwise, we will translate asterisks and do an
- // actual pattern match against the two strings to see if they match.
- if ($pattern == $value) {
- return true;
- }
-
- $pattern = preg_quote($pattern, '#');
-
- // Asterisks are translated into zero-or-more regular expression wildcards
- // to make it convenient to check if the strings starts with the given
- // pattern such as "library/*", making any string check convenient.
- $pattern = str_replace('\*', '.*', $pattern);
-
- if (preg_match('#^'.$pattern.'\z#u', $value) === 1) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Convert a string to kebab case.
- *
- * @param string $value
- * @return string
- */
- public static function kebab($value)
- {
- return static::snake($value, '-');
- }
-
- /**
- * Return the length of the given string.
- *
- * @param string $value
- * @param string $encoding
- * @return int
- */
- public static function length($value, $encoding = null)
- {
- if ($encoding) {
- return mb_strlen($value, $encoding);
- }
-
- return mb_strlen($value);
- }
-
- /**
- * Limit the number of characters in a string.
- *
- * @param string $value
- * @param int $limit
- * @param string $end
- * @return string
- */
- public static function limit($value, $limit = 100, $end = '...')
- {
- if (mb_strwidth($value, 'UTF-8') <= $limit) {
- return $value;
- }
-
- return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end;
- }
-
- /**
- * Convert the given string to lower-case.
- *
- * @param string $value
- * @return string
- */
- public static function lower($value)
- {
- return mb_strtolower($value, 'UTF-8');
- }
-
- /**
- * Limit the number of words in a string.
- *
- * @param string $value
- * @param int $words
- * @param string $end
- * @return string
- */
- public static function words($value, $words = 100, $end = '...')
- {
- preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
-
- if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) {
- return $value;
- }
-
- return rtrim($matches[0]).$end;
- }
-
- /**
- * Parse a Class@method style callback into class and method.
- *
- * @param string $callback
- * @param string|null $default
- * @return array
- */
- public static function parseCallback($callback, $default = null)
- {
- return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
- }
-
- /**
- * Get the plural form of an English word.
- *
- * @param string $value
- * @param int $count
- * @return string
- */
- public static function plural($value, $count = 2)
- {
- return Pluralizer::plural($value, $count);
- }
-
- /**
- * Pluralize the last word of an English, studly caps case string.
- *
- * @param string $value
- * @param int $count
- * @return string
- */
- public static function pluralStudly($value, $count = 2)
- {
- $parts = preg_split('/(.)(?=[A-Z])/u', $value, -1, PREG_SPLIT_DELIM_CAPTURE);
-
- $lastWord = array_pop($parts);
-
- return implode('', $parts).self::plural($lastWord, $count);
- }
-
- /**
- * Generate a more truly "random" alpha-numeric string.
- *
- * @param int $length
- * @return string
- */
- public static function random($length = 16)
- {
- $string = '';
-
- while (($len = strlen($string)) < $length) {
- $size = $length - $len;
-
- $bytes = random_bytes($size);
-
- $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
- }
-
- return $string;
- }
-
- /**
- * Replace a given value in the string sequentially with an array.
- *
- * @param string $search
- * @param array $replace
- * @param string $subject
- * @return string
- */
- public static function replaceArray($search, array $replace, $subject)
- {
- $segments = explode($search, $subject);
-
- $result = array_shift($segments);
-
- foreach ($segments as $segment) {
- $result .= (array_shift($replace) ?? $search).$segment;
- }
-
- return $result;
- }
-
- /**
- * Replace the first occurrence of a given value in the string.
- *
- * @param string $search
- * @param string $replace
- * @param string $subject
- * @return string
- */
- public static function replaceFirst($search, $replace, $subject)
- {
- if ($search == '') {
- return $subject;
- }
-
- $position = strpos($subject, $search);
-
- if ($position !== false) {
- return substr_replace($subject, $replace, $position, strlen($search));
- }
-
- return $subject;
- }
-
- /**
- * Replace the last occurrence of a given value in the string.
- *
- * @param string $search
- * @param string $replace
- * @param string $subject
- * @return string
- */
- public static function replaceLast($search, $replace, $subject)
- {
- $position = strrpos($subject, $search);
-
- if ($position !== false) {
- return substr_replace($subject, $replace, $position, strlen($search));
- }
-
- return $subject;
- }
-
- /**
- * Begin a string with a single instance of a given value.
- *
- * @param string $value
- * @param string $prefix
- * @return string
- */
- public static function start($value, $prefix)
- {
- $quoted = preg_quote($prefix, '/');
-
- return $prefix.preg_replace('/^(?:'.$quoted.')+/u', '', $value);
- }
-
- /**
- * Convert the given string to upper-case.
- *
- * @param string $value
- * @return string
- */
- public static function upper($value)
- {
- return mb_strtoupper($value, 'UTF-8');
- }
-
- /**
- * Convert the given string to title case.
- *
- * @param string $value
- * @return string
- */
- public static function title($value)
- {
- return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
- }
-
- /**
- * Get the singular form of an English word.
- *
- * @param string $value
- * @return string
- */
- public static function singular($value)
- {
- return Pluralizer::singular($value);
- }
-
- /**
- * Generate a URL friendly "slug" from a given string.
- *
- * @param string $title
- * @param string $separator
- * @param string|null $language
- * @return string
- */
- public static function slug($title, $separator = '-', $language = 'en')
- {
- $title = $language ? static::ascii($title, $language) : $title;
-
- // Convert all dashes/underscores into separator
- $flip = $separator === '-' ? '_' : '-';
-
- $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);
-
- // Replace @ with the word 'at'
- $title = str_replace('@', $separator.'at'.$separator, $title);
-
- // Remove all characters that are not the separator, letters, numbers, or whitespace.
- $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', static::lower($title));
-
- // Replace all separator characters and whitespace by a single separator
- $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
-
- return trim($title, $separator);
- }
-
- /**
- * Convert a string to snake case.
- *
- * @param string $value
- * @param string $delimiter
- * @return string
- */
- public static function snake($value, $delimiter = '_')
- {
- $key = $value;
-
- if (isset(static::$snakeCache[$key][$delimiter])) {
- return static::$snakeCache[$key][$delimiter];
- }
-
- if (! ctype_lower($value)) {
- $value = preg_replace('/\s+/u', '', ucwords($value));
-
- $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
- }
-
- return static::$snakeCache[$key][$delimiter] = $value;
- }
-
- /**
- * Determine if a given string starts with a given substring.
- *
- * @param string $haystack
- * @param string|array $needles
- * @return bool
- */
- public static function startsWith($haystack, $needles)
- {
- foreach ((array) $needles as $needle) {
- if ($needle !== '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Convert a value to studly caps case.
- *
- * @param string $value
- * @return string
- */
- public static function studly($value)
- {
- $key = $value;
-
- if (isset(static::$studlyCache[$key])) {
- return static::$studlyCache[$key];
- }
-
- $value = ucwords(str_replace(['-', '_'], ' ', $value));
-
- return static::$studlyCache[$key] = str_replace(' ', '', $value);
- }
-
- /**
- * Returns the portion of string specified by the start and length parameters.
- *
- * @param string $string
- * @param int $start
- * @param int|null $length
- * @return string
- */
- public static function substr($string, $start, $length = null)
- {
- return mb_substr($string, $start, $length, 'UTF-8');
- }
-
- /**
- * Make a string's first character uppercase.
- *
- * @param string $string
- * @return string
- */
- public static function ucfirst($string)
- {
- return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
- }
-
- /**
- * Generate a UUID (version 4).
- *
- * @return \Ramsey\Uuid\UuidInterface
- */
- public static function uuid()
- {
- return Uuid::uuid4();
- }
-
- /**
- * Generate a time-ordered UUID (version 4).
- *
- * @return \Ramsey\Uuid\UuidInterface
- */
- public static function orderedUuid()
- {
- $factory = new UuidFactory;
-
- $factory->setRandomGenerator(new CombGenerator(
- $factory->getRandomGenerator(),
- $factory->getNumberConverter()
- ));
-
- $factory->setCodec(new TimestampFirstCombCodec(
- $factory->getUuidBuilder()
- ));
-
- return $factory->uuid4();
- }
-
- /**
- * Returns the replacements for the ascii method.
- *
- * Note: Adapted from Stringy\Stringy.
- *
- * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt
- *
- * @return array
- */
- protected static function charsArray()
- {
- static $charsArray;
-
- if (isset($charsArray)) {
- return $charsArray;
- }
-
- return $charsArray = [
- '0' => ['°', '₀', '۰', '0'],
- '1' => ['¹', '₁', '۱', '1'],
- '2' => ['²', '₂', '۲', '2'],
- '3' => ['³', '₃', '۳', '3'],
- '4' => ['⁴', '₄', '۴', '٤', '4'],
- '5' => ['⁵', '₅', '۵', '٥', '5'],
- '6' => ['⁶', '₆', '۶', '٦', '6'],
- '7' => ['⁷', '₇', '۷', '7'],
- '8' => ['⁸', '₈', '۸', '8'],
- '9' => ['⁹', '₉', '۹', '9'],
- 'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا', 'a', 'ä'],
- 'b' => ['б', 'β', 'ب', 'ဗ', 'ბ', 'b'],
- 'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ', 'c'],
- 'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ', 'd'],
- 'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ', 'e'],
- 'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ', 'f'],
- 'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ', 'g'],
- 'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ', 'h'],
- 'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ', 'ی', 'i'],
- 'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج', 'j'],
- 'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک', 'k'],
- 'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ', 'l'],
- 'm' => ['м', 'μ', 'م', 'မ', 'მ', 'm'],
- 'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ', 'n'],
- 'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ', 'o', 'ö'],
- 'p' => ['п', 'π', 'ပ', 'პ', 'پ', 'p'],
- 'q' => ['ყ', 'q'],
- 'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ', 'r'],
- 's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს', 's'],
- 't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ', 't'],
- 'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ', 'u', 'ў', 'ü'],
- 'v' => ['в', 'ვ', 'ϐ', 'v'],
- 'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ', 'w'],
- 'x' => ['χ', 'ξ', 'x'],
- 'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ', 'y'],
- 'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ', 'z'],
- 'aa' => ['ع', 'आ', 'آ'],
- 'ae' => ['æ', 'ǽ'],
- 'ai' => ['ऐ'],
- 'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
- 'dj' => ['ђ', 'đ'],
- 'dz' => ['џ', 'ძ'],
- 'ei' => ['ऍ'],
- 'gh' => ['غ', 'ღ'],
- 'ii' => ['ई'],
- 'ij' => ['ij'],
- 'kh' => ['х', 'خ', 'ხ'],
- 'lj' => ['љ'],
- 'nj' => ['њ'],
- 'oe' => ['ö', 'œ', 'ؤ'],
- 'oi' => ['ऑ'],
- 'oii' => ['ऒ'],
- 'ps' => ['ψ'],
- 'sh' => ['ш', 'შ', 'ش'],
- 'shch' => ['щ'],
- 'ss' => ['ß'],
- 'sx' => ['ŝ'],
- 'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
- 'ts' => ['ц', 'ც', 'წ'],
- 'ue' => ['ü'],
- 'uu' => ['ऊ'],
- 'ya' => ['я'],
- 'yu' => ['ю'],
- 'zh' => ['ж', 'ჟ', 'ژ'],
- '(c)' => ['©'],
- 'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ', 'A', 'Ä'],
- 'B' => ['Б', 'Β', 'ब', 'B'],
- 'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ', 'C'],
- 'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ', 'D'],
- 'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə', 'E'],
- 'F' => ['Ф', 'Φ', 'F'],
- 'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ', 'G'],
- 'H' => ['Η', 'Ή', 'Ħ', 'H'],
- 'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ', 'I'],
- 'J' => ['J'],
- 'K' => ['К', 'Κ', 'K'],
- 'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल', 'L'],
- 'M' => ['М', 'Μ', 'M'],
- 'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν', 'N'],
- 'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ', 'O', 'Ö'],
- 'P' => ['П', 'Π', 'P'],
- 'Q' => ['Q'],
- 'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ', 'R'],
- 'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ', 'S'],
- 'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ', 'T'],
- 'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ', 'U', 'Ў', 'Ü'],
- 'V' => ['В', 'V'],
- 'W' => ['Ω', 'Ώ', 'Ŵ', 'W'],
- 'X' => ['Χ', 'Ξ', 'X'],
- 'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ', 'Y'],
- 'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ', 'Z'],
- 'AE' => ['Æ', 'Ǽ'],
- 'Ch' => ['Ч'],
- 'Dj' => ['Ђ'],
- 'Dz' => ['Џ'],
- 'Gx' => ['Ĝ'],
- 'Hx' => ['Ĥ'],
- 'Ij' => ['IJ'],
- 'Jx' => ['Ĵ'],
- 'Kh' => ['Х'],
- 'Lj' => ['Љ'],
- 'Nj' => ['Њ'],
- 'Oe' => ['Œ'],
- 'Ps' => ['Ψ'],
- 'Sh' => ['Ш'],
- 'Shch' => ['Щ'],
- 'Ss' => ['ẞ'],
- 'Th' => ['Þ'],
- 'Ts' => ['Ц'],
- 'Ya' => ['Я'],
- 'Yu' => ['Ю'],
- 'Zh' => ['Ж'],
- ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80", "\xEF\xBE\xA0"],
- ];
- }
-
- /**
- * Returns the language specific replacements for the ascii method.
- *
- * Note: Adapted from Stringy\Stringy.
- *
- * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt
- *
- * @param string $language
- * @return array|null
- */
- protected static function languageSpecificCharsArray($language)
- {
- static $languageSpecific;
-
- if (! isset($languageSpecific)) {
- $languageSpecific = [
- 'bg' => [
- ['х', 'Х', 'щ', 'Щ', 'ъ', 'Ъ', 'ь', 'Ь'],
- ['h', 'H', 'sht', 'SHT', 'a', 'А', 'y', 'Y'],
- ],
- 'da' => [
- ['æ', 'ø', 'å', 'Æ', 'Ø', 'Å'],
- ['ae', 'oe', 'aa', 'Ae', 'Oe', 'Aa'],
- ],
- 'de' => [
- ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'],
- ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'],
- ],
- 'ro' => [
- ['ă', 'â', 'î', 'ș', 'ț', 'Ă', 'Â', 'Î', 'Ș', 'Ț'],
- ['a', 'a', 'i', 's', 't', 'A', 'A', 'I', 'S', 'T'],
- ],
- ];
- }
-
- return $languageSpecific[$language] ?? null;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Testing\Fakes;
-
-use Illuminate\Contracts\Bus\Dispatcher;
-use PHPUnit\Framework\Assert as PHPUnit;
-
-class BusFake implements Dispatcher
-{
- /**
- * The commands that have been dispatched.
- *
- * @var array
- */
- protected $commands = [];
-
- /**
- * Assert if a job was dispatched based on a truth-test callback.
- *
- * @param string $command
- * @param callable|int|null $callback
- * @return void
- */
- public function assertDispatched($command, $callback = null)
- {
- if (is_numeric($callback)) {
- return $this->assertDispatchedTimes($command, $callback);
- }
-
- PHPUnit::assertTrue(
- $this->dispatched($command, $callback)->count() > 0,
- "The expected [{$command}] job was not dispatched."
- );
- }
-
- /**
- * Assert if a job was pushed a number of times.
- *
- * @param string $command
- * @param int $times
- * @return void
- */
- protected function assertDispatchedTimes($command, $times = 1)
- {
- PHPUnit::assertTrue(
- ($count = $this->dispatched($command)->count()) === $times,
- "The expected [{$command}] job was pushed {$count} times instead of {$times} times."
- );
- }
-
- /**
- * Determine if a job was dispatched based on a truth-test callback.
- *
- * @param string $command
- * @param callable|null $callback
- * @return void
- */
- public function assertNotDispatched($command, $callback = null)
- {
- PHPUnit::assertTrue(
- $this->dispatched($command, $callback)->count() === 0,
- "The unexpected [{$command}] job was dispatched."
- );
- }
-
- /**
- * Get all of the jobs matching a truth-test callback.
- *
- * @param string $command
- * @param callable|null $callback
- * @return \Illuminate\Support\Collection
- */
- public function dispatched($command, $callback = null)
- {
- if (! $this->hasDispatched($command)) {
- return collect();
- }
-
- $callback = $callback ?: function () {
- return true;
- };
-
- return collect($this->commands[$command])->filter(function ($command) use ($callback) {
- return $callback($command);
- });
- }
-
- /**
- * Determine if there are any stored commands for a given class.
- *
- * @param string $command
- * @return bool
- */
- public function hasDispatched($command)
- {
- return isset($this->commands[$command]) && ! empty($this->commands[$command]);
- }
-
- /**
- * Dispatch a command to its appropriate handler.
- *
- * @param mixed $command
- * @return mixed
- */
- public function dispatch($command)
- {
- return $this->dispatchNow($command);
- }
-
- /**
- * Dispatch a command to its appropriate handler in the current process.
- *
- * @param mixed $command
- * @param mixed $handler
- * @return mixed
- */
- public function dispatchNow($command, $handler = null)
- {
- $this->commands[get_class($command)][] = $command;
- }
-
- /**
- * Set the pipes commands should be piped through before dispatching.
- *
- * @param array $pipes
- * @return $this
- */
- public function pipeThrough(array $pipes)
- {
- return $this;
- }
-
- /**
- * Determine if the given command has a handler.
- *
- * @param mixed $command
- * @return bool
- */
- public function hasCommandHandler($command)
- {
- return false;
- }
-
- /**
- * Retrieve the handler for a command.
- *
- * @param mixed $command
- * @return mixed
- */
- public function getCommandHandler($command)
- {
- return false;
- }
-
- /**
- * Map a command to a handler.
- *
- * @param array $map
- * @return $this
- */
- public function map(array $map)
- {
- return $this;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Testing\Fakes;
-
-use Closure;
-use Illuminate\Support\Arr;
-use PHPUnit\Framework\Assert as PHPUnit;
-use Illuminate\Contracts\Events\Dispatcher;
-
-class EventFake implements Dispatcher
-{
- /**
- * The original event dispatcher.
- *
- * @var \Illuminate\Contracts\Events\Dispatcher
- */
- protected $dispatcher;
-
- /**
- * The event types that should be intercepted instead of dispatched.
- *
- * @var array
- */
- protected $eventsToFake;
-
- /**
- * All of the events that have been intercepted keyed by type.
- *
- * @var array
- */
- protected $events = [];
-
- /**
- * Create a new event fake instance.
- *
- * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
- * @param array|string $eventsToFake
- * @return void
- */
- public function __construct(Dispatcher $dispatcher, $eventsToFake = [])
- {
- $this->dispatcher = $dispatcher;
-
- $this->eventsToFake = Arr::wrap($eventsToFake);
- }
-
- /**
- * Assert if an event was dispatched based on a truth-test callback.
- *
- * @param string $event
- * @param callable|int|null $callback
- * @return void
- */
- public function assertDispatched($event, $callback = null)
- {
- if (is_int($callback)) {
- return $this->assertDispatchedTimes($event, $callback);
- }
-
- PHPUnit::assertTrue(
- $this->dispatched($event, $callback)->count() > 0,
- "The expected [{$event}] event was not dispatched."
- );
- }
-
- /**
- * Assert if a event was dispatched a number of times.
- *
- * @param string $event
- * @param int $times
- * @return void
- */
- public function assertDispatchedTimes($event, $times = 1)
- {
- PHPUnit::assertTrue(
- ($count = $this->dispatched($event)->count()) === $times,
- "The expected [{$event}] event was dispatched {$count} times instead of {$times} times."
- );
- }
-
- /**
- * Determine if an event was dispatched based on a truth-test callback.
- *
- * @param string $event
- * @param callable|null $callback
- * @return void
- */
- public function assertNotDispatched($event, $callback = null)
- {
- PHPUnit::assertTrue(
- $this->dispatched($event, $callback)->count() === 0,
- "The unexpected [{$event}] event was dispatched."
- );
- }
-
- /**
- * Get all of the events matching a truth-test callback.
- *
- * @param string $event
- * @param callable|null $callback
- * @return \Illuminate\Support\Collection
- */
- public function dispatched($event, $callback = null)
- {
- if (! $this->hasDispatched($event)) {
- return collect();
- }
-
- $callback = $callback ?: function () {
- return true;
- };
-
- return collect($this->events[$event])->filter(function ($arguments) use ($callback) {
- return $callback(...$arguments);
- });
- }
-
- /**
- * Determine if the given event has been dispatched.
- *
- * @param string $event
- * @return bool
- */
- public function hasDispatched($event)
- {
- return isset($this->events[$event]) && ! empty($this->events[$event]);
- }
-
- /**
- * Register an event listener with the dispatcher.
- *
- * @param string|array $events
- * @param mixed $listener
- * @return void
- */
- public function listen($events, $listener)
- {
- $this->dispatcher->listen($events, $listener);
- }
-
- /**
- * Determine if a given event has listeners.
- *
- * @param string $eventName
- * @return bool
- */
- public function hasListeners($eventName)
- {
- return $this->dispatcher->hasListeners($eventName);
- }
-
- /**
- * Register an event and payload to be dispatched later.
- *
- * @param string $event
- * @param array $payload
- * @return void
- */
- public function push($event, $payload = [])
- {
- //
- }
-
- /**
- * Register an event subscriber with the dispatcher.
- *
- * @param object|string $subscriber
- * @return void
- */
- public function subscribe($subscriber)
- {
- $this->dispatcher->subscribe($subscriber);
- }
-
- /**
- * Flush a set of pushed events.
- *
- * @param string $event
- * @return void
- */
- public function flush($event)
- {
- //
- }
-
- /**
- * Fire an event and call the listeners.
- *
- * @param string|object $event
- * @param mixed $payload
- * @param bool $halt
- * @return array|null
- */
- public function dispatch($event, $payload = [], $halt = false)
- {
- $name = is_object($event) ? get_class($event) : (string) $event;
-
- if ($this->shouldFakeEvent($name, $payload)) {
- $this->events[$name][] = func_get_args();
- } else {
- return $this->dispatcher->dispatch($event, $payload, $halt);
- }
- }
-
- /**
- * Determine if an event should be faked or actually dispatched.
- *
- * @param string $eventName
- * @param mixed $payload
- * @return bool
- */
- protected function shouldFakeEvent($eventName, $payload)
- {
- if (empty($this->eventsToFake)) {
- return true;
- }
-
- return collect($this->eventsToFake)
- ->filter(function ($event) use ($eventName, $payload) {
- return $event instanceof Closure
- ? $event($eventName, $payload)
- : $event === $eventName;
- })
- ->isNotEmpty();
- }
-
- /**
- * Remove a set of listeners from the dispatcher.
- *
- * @param string $event
- * @return void
- */
- public function forget($event)
- {
- //
- }
-
- /**
- * Forget all of the queued listeners.
- *
- * @return void
- */
- public function forgetPushed()
- {
- //
- }
-
- /**
- * Dispatch an event and call the listeners.
- *
- * @param string|object $event
- * @param mixed $payload
- * @return void
- */
- public function until($event, $payload = [])
- {
- return $this->dispatch($event, $payload, true);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Testing\Fakes;
-
-use Illuminate\Contracts\Mail\Mailer;
-use Illuminate\Contracts\Mail\Mailable;
-use Illuminate\Contracts\Mail\MailQueue;
-use PHPUnit\Framework\Assert as PHPUnit;
-use Illuminate\Contracts\Queue\ShouldQueue;
-
-class MailFake implements Mailer, MailQueue
-{
- /**
- * All of the mailables that have been sent.
- *
- * @var array
- */
- protected $mailables = [];
-
- /**
- * All of the mailables that have been queued.
- *
- * @var array
- */
- protected $queuedMailables = [];
-
- /**
- * Assert if a mailable was sent based on a truth-test callback.
- *
- * @param string $mailable
- * @param callable|int|null $callback
- * @return void
- */
- public function assertSent($mailable, $callback = null)
- {
- if (is_numeric($callback)) {
- return $this->assertSentTimes($mailable, $callback);
- }
-
- $message = "The expected [{$mailable}] mailable was not sent.";
-
- if (count($this->queuedMailables) > 0) {
- $message .= ' Did you mean to use assertQueued() instead?';
- }
-
- PHPUnit::assertTrue(
- $this->sent($mailable, $callback)->count() > 0,
- $message
- );
- }
-
- /**
- * Assert if a mailable was sent a number of times.
- *
- * @param string $mailable
- * @param int $times
- * @return void
- */
- protected function assertSentTimes($mailable, $times = 1)
- {
- PHPUnit::assertTrue(
- ($count = $this->sent($mailable)->count()) === $times,
- "The expected [{$mailable}] mailable was sent {$count} times instead of {$times} times."
- );
- }
-
- /**
- * Determine if a mailable was not sent based on a truth-test callback.
- *
- * @param string $mailable
- * @param callable|null $callback
- * @return void
- */
- public function assertNotSent($mailable, $callback = null)
- {
- PHPUnit::assertTrue(
- $this->sent($mailable, $callback)->count() === 0,
- "The unexpected [{$mailable}] mailable was sent."
- );
- }
-
- /**
- * Assert that no mailables were sent.
- *
- * @return void
- */
- public function assertNothingSent()
- {
- PHPUnit::assertEmpty($this->mailables, 'Mailables were sent unexpectedly.');
- }
-
- /**
- * Assert if a mailable was queued based on a truth-test callback.
- *
- * @param string $mailable
- * @param callable|int|null $callback
- * @return void
- */
- public function assertQueued($mailable, $callback = null)
- {
- if (is_numeric($callback)) {
- return $this->assertQueuedTimes($mailable, $callback);
- }
-
- PHPUnit::assertTrue(
- $this->queued($mailable, $callback)->count() > 0,
- "The expected [{$mailable}] mailable was not queued."
- );
- }
-
- /**
- * Assert if a mailable was queued a number of times.
- *
- * @param string $mailable
- * @param int $times
- * @return void
- */
- protected function assertQueuedTimes($mailable, $times = 1)
- {
- PHPUnit::assertTrue(
- ($count = $this->queued($mailable)->count()) === $times,
- "The expected [{$mailable}] mailable was queued {$count} times instead of {$times} times."
- );
- }
-
- /**
- * Determine if a mailable was not queued based on a truth-test callback.
- *
- * @param string $mailable
- * @param callable|null $callback
- * @return void
- */
- public function assertNotQueued($mailable, $callback = null)
- {
- PHPUnit::assertTrue(
- $this->queued($mailable, $callback)->count() === 0,
- "The unexpected [{$mailable}] mailable was queued."
- );
- }
-
- /**
- * Assert that no mailables were queued.
- *
- * @return void
- */
- public function assertNothingQueued()
- {
- PHPUnit::assertEmpty($this->queuedMailables, 'Mailables were queued unexpectedly.');
- }
-
- /**
- * Get all of the mailables matching a truth-test callback.
- *
- * @param string $mailable
- * @param callable|null $callback
- * @return \Illuminate\Support\Collection
- */
- public function sent($mailable, $callback = null)
- {
- if (! $this->hasSent($mailable)) {
- return collect();
- }
-
- $callback = $callback ?: function () {
- return true;
- };
-
- return $this->mailablesOf($mailable)->filter(function ($mailable) use ($callback) {
- return $callback($mailable);
- });
- }
-
- /**
- * Determine if the given mailable has been sent.
- *
- * @param string $mailable
- * @return bool
- */
- public function hasSent($mailable)
- {
- return $this->mailablesOf($mailable)->count() > 0;
- }
-
- /**
- * Get all of the queued mailables matching a truth-test callback.
- *
- * @param string $mailable
- * @param callable|null $callback
- * @return \Illuminate\Support\Collection
- */
- public function queued($mailable, $callback = null)
- {
- if (! $this->hasQueued($mailable)) {
- return collect();
- }
-
- $callback = $callback ?: function () {
- return true;
- };
-
- return $this->queuedMailablesOf($mailable)->filter(function ($mailable) use ($callback) {
- return $callback($mailable);
- });
- }
-
- /**
- * Determine if the given mailable has been queued.
- *
- * @param string $mailable
- * @return bool
- */
- public function hasQueued($mailable)
- {
- return $this->queuedMailablesOf($mailable)->count() > 0;
- }
-
- /**
- * Get all of the mailed mailables for a given type.
- *
- * @param string $type
- * @return \Illuminate\Support\Collection
- */
- protected function mailablesOf($type)
- {
- return collect($this->mailables)->filter(function ($mailable) use ($type) {
- return $mailable instanceof $type;
- });
- }
-
- /**
- * Get all of the mailed mailables for a given type.
- *
- * @param string $type
- * @return \Illuminate\Support\Collection
- */
- protected function queuedMailablesOf($type)
- {
- return collect($this->queuedMailables)->filter(function ($mailable) use ($type) {
- return $mailable instanceof $type;
- });
- }
-
- /**
- * Begin the process of mailing a mailable class instance.
- *
- * @param mixed $users
- * @return \Illuminate\Mail\PendingMail
- */
- public function to($users)
- {
- return (new PendingMailFake($this))->to($users);
- }
-
- /**
- * Begin the process of mailing a mailable class instance.
- *
- * @param mixed $users
- * @return \Illuminate\Mail\PendingMail
- */
- public function bcc($users)
- {
- return (new PendingMailFake($this))->bcc($users);
- }
-
- /**
- * Send a new message with only a raw text part.
- *
- * @param string $text
- * @param \Closure|string $callback
- * @return void
- */
- public function raw($text, $callback)
- {
- //
- }
-
- /**
- * Send a new message using a view.
- *
- * @param string|array $view
- * @param array $data
- * @param \Closure|string $callback
- * @return void
- */
- public function send($view, array $data = [], $callback = null)
- {
- if (! $view instanceof Mailable) {
- return;
- }
-
- if ($view instanceof ShouldQueue) {
- return $this->queue($view, $data);
- }
-
- $this->mailables[] = $view;
- }
-
- /**
- * Queue a new e-mail message for sending.
- *
- * @param string|array $view
- * @param string|null $queue
- * @return mixed
- */
- public function queue($view, $queue = null)
- {
- if (! $view instanceof Mailable) {
- return;
- }
-
- $this->queuedMailables[] = $view;
- }
-
- /**
- * Queue a new e-mail message for sending after (n) seconds.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param string|array|\Illuminate\Contracts\Mail\Mailable $view
- * @param string $queue
- * @return mixed
- */
- public function later($delay, $view, $queue = null)
- {
- $this->queue($view, $queue);
- }
-
- /**
- * Get the array of failed recipients.
- *
- * @return array
- */
- public function failures()
- {
- return [];
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Testing\Fakes;
-
-use Illuminate\Support\Str;
-use Illuminate\Support\Collection;
-use Illuminate\Support\Traits\Macroable;
-use PHPUnit\Framework\Assert as PHPUnit;
-use Illuminate\Contracts\Translation\HasLocalePreference;
-use Illuminate\Contracts\Notifications\Factory as NotificationFactory;
-use Illuminate\Contracts\Notifications\Dispatcher as NotificationDispatcher;
-
-class NotificationFake implements NotificationFactory, NotificationDispatcher
-{
- use Macroable;
-
- /**
- * All of the notifications that have been sent.
- *
- * @var array
- */
- protected $notifications = [];
-
- /**
- * Locale used when sending notifications.
- *
- * @var string|null
- */
- public $locale;
-
- /**
- * Assert if a notification was sent based on a truth-test callback.
- *
- * @param mixed $notifiable
- * @param string $notification
- * @param callable|null $callback
- * @return void
- */
- public function assertSentTo($notifiable, $notification, $callback = null)
- {
- if (is_array($notifiable) || $notifiable instanceof Collection) {
- foreach ($notifiable as $singleNotifiable) {
- $this->assertSentTo($singleNotifiable, $notification, $callback);
- }
-
- return;
- }
-
- if (is_numeric($callback)) {
- return $this->assertSentToTimes($notifiable, $notification, $callback);
- }
-
- PHPUnit::assertTrue(
- $this->sent($notifiable, $notification, $callback)->count() > 0,
- "The expected [{$notification}] notification was not sent."
- );
- }
-
- /**
- * Assert if a notification was sent a number of times.
- *
- * @param mixed $notifiable
- * @param string $notification
- * @param int $times
- * @return void
- */
- public function assertSentToTimes($notifiable, $notification, $times = 1)
- {
- PHPUnit::assertTrue(
- ($count = $this->sent($notifiable, $notification)->count()) === $times,
- "Expected [{$notification}] to be sent {$times} times, but was sent {$count} times."
- );
- }
-
- /**
- * Determine if a notification was sent based on a truth-test callback.
- *
- * @param mixed $notifiable
- * @param string $notification
- * @param callable|null $callback
- * @return void
- */
- public function assertNotSentTo($notifiable, $notification, $callback = null)
- {
- if (is_array($notifiable) || $notifiable instanceof Collection) {
- foreach ($notifiable as $singleNotifiable) {
- $this->assertNotSentTo($singleNotifiable, $notification, $callback);
- }
-
- return;
- }
-
- PHPUnit::assertTrue(
- $this->sent($notifiable, $notification, $callback)->count() === 0,
- "The unexpected [{$notification}] notification was sent."
- );
- }
-
- /**
- * Assert that no notifications were sent.
- *
- * @return void
- */
- public function assertNothingSent()
- {
- PHPUnit::assertEmpty($this->notifications, 'Notifications were sent unexpectedly.');
- }
-
- /**
- * Assert the total amount of times a notification was sent.
- *
- * @param int $expectedCount
- * @param string $notification
- * @return void
- */
- public function assertTimesSent($expectedCount, $notification)
- {
- $actualCount = collect($this->notifications)
- ->flatten(1)
- ->reduce(function ($count, $sent) use ($notification) {
- return $count + count($sent[$notification] ?? []);
- }, 0);
-
- PHPUnit::assertSame(
- $expectedCount, $actualCount,
- "Expected [{$notification}] to be sent {$expectedCount} times, but was sent {$actualCount} times."
- );
- }
-
- /**
- * Get all of the notifications matching a truth-test callback.
- *
- * @param mixed $notifiable
- * @param string $notification
- * @param callable|null $callback
- * @return \Illuminate\Support\Collection
- */
- public function sent($notifiable, $notification, $callback = null)
- {
- if (! $this->hasSent($notifiable, $notification)) {
- return collect();
- }
-
- $callback = $callback ?: function () {
- return true;
- };
-
- $notifications = collect($this->notificationsFor($notifiable, $notification));
-
- return $notifications->filter(function ($arguments) use ($callback) {
- return $callback(...array_values($arguments));
- })->pluck('notification');
- }
-
- /**
- * Determine if there are more notifications left to inspect.
- *
- * @param mixed $notifiable
- * @param string $notification
- * @return bool
- */
- public function hasSent($notifiable, $notification)
- {
- return ! empty($this->notificationsFor($notifiable, $notification));
- }
-
- /**
- * Get all of the notifications for a notifiable entity by type.
- *
- * @param mixed $notifiable
- * @param string $notification
- * @return array
- */
- protected function notificationsFor($notifiable, $notification)
- {
- return $this->notifications[get_class($notifiable)][$notifiable->getKey()][$notification] ?? [];
- }
-
- /**
- * Send the given notification to the given notifiable entities.
- *
- * @param \Illuminate\Support\Collection|array|mixed $notifiables
- * @param mixed $notification
- * @return void
- */
- public function send($notifiables, $notification)
- {
- return $this->sendNow($notifiables, $notification);
- }
-
- /**
- * Send the given notification immediately.
- *
- * @param \Illuminate\Support\Collection|array|mixed $notifiables
- * @param mixed $notification
- * @return void
- */
- public function sendNow($notifiables, $notification)
- {
- if (! $notifiables instanceof Collection && ! is_array($notifiables)) {
- $notifiables = [$notifiables];
- }
-
- foreach ($notifiables as $notifiable) {
- if (! $notification->id) {
- $notification->id = Str::uuid()->toString();
- }
-
- $this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [
- 'notification' => $notification,
- 'channels' => $notification->via($notifiable),
- 'notifiable' => $notifiable,
- 'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) {
- if ($notifiable instanceof HasLocalePreference) {
- return $notifiable->preferredLocale();
- }
- }),
- ];
- }
- }
-
- /**
- * Get a channel instance by name.
- *
- * @param string|null $name
- * @return mixed
- */
- public function channel($name = null)
- {
- //
- }
-
- /**
- * Set the locale of notifications.
- *
- * @param string $locale
- * @return $this
- */
- public function locale($locale)
- {
- $this->locale = $locale;
-
- return $this;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Testing\Fakes;
-
-use Illuminate\Mail\PendingMail;
-use Illuminate\Contracts\Mail\Mailable;
-
-class PendingMailFake extends PendingMail
-{
- /**
- * Create a new instance.
- *
- * @param \Illuminate\Support\Testing\Fakes\MailFake $mailer
- * @return void
- */
- public function __construct($mailer)
- {
- $this->mailer = $mailer;
- }
-
- /**
- * Send a new mailable message instance.
- *
- * @param \Illuminate\Contracts\Mail\Mailable $mailable;
- * @return mixed
- */
- public function send(Mailable $mailable)
- {
- return $this->sendNow($mailable);
- }
-
- /**
- * Send a mailable message immediately.
- *
- * @param \Illuminate\Contracts\Mail\Mailable $mailable;
- * @return mixed
- */
- public function sendNow(Mailable $mailable)
- {
- $this->mailer->send($this->fill($mailable));
- }
-
- /**
- * Push the given mailable onto the queue.
- *
- * @param \Illuminate\Contracts\Mail\Mailable $mailable;
- * @return mixed
- */
- public function queue(Mailable $mailable)
- {
- return $this->mailer->queue($this->fill($mailable));
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Testing\Fakes;
-
-use BadMethodCallException;
-use Illuminate\Queue\QueueManager;
-use Illuminate\Contracts\Queue\Queue;
-use PHPUnit\Framework\Assert as PHPUnit;
-
-class QueueFake extends QueueManager implements Queue
-{
- /**
- * All of the jobs that have been pushed.
- *
- * @var array
- */
- protected $jobs = [];
-
- /**
- * Assert if a job was pushed based on a truth-test callback.
- *
- * @param string $job
- * @param callable|int|null $callback
- * @return void
- */
- public function assertPushed($job, $callback = null)
- {
- if (is_numeric($callback)) {
- return $this->assertPushedTimes($job, $callback);
- }
-
- PHPUnit::assertTrue(
- $this->pushed($job, $callback)->count() > 0,
- "The expected [{$job}] job was not pushed."
- );
- }
-
- /**
- * Assert if a job was pushed a number of times.
- *
- * @param string $job
- * @param int $times
- * @return void
- */
- protected function assertPushedTimes($job, $times = 1)
- {
- PHPUnit::assertTrue(
- ($count = $this->pushed($job)->count()) === $times,
- "The expected [{$job}] job was pushed {$count} times instead of {$times} times."
- );
- }
-
- /**
- * Assert if a job was pushed based on a truth-test callback.
- *
- * @param string $queue
- * @param string $job
- * @param callable|null $callback
- * @return void
- */
- public function assertPushedOn($queue, $job, $callback = null)
- {
- return $this->assertPushed($job, function ($job, $pushedQueue) use ($callback, $queue) {
- if ($pushedQueue !== $queue) {
- return false;
- }
-
- return $callback ? $callback(...func_get_args()) : true;
- });
- }
-
- /**
- * Assert if a job was pushed with chained jobs based on a truth-test callback.
- *
- * @param string $job
- * @param array $expectedChain
- * @param callable|null $callback
- * @return void
- */
- public function assertPushedWithChain($job, $expectedChain = [], $callback = null)
- {
- PHPUnit::assertTrue(
- $this->pushed($job, $callback)->isNotEmpty(),
- "The expected [{$job}] job was not pushed."
- );
-
- PHPUnit::assertTrue(
- collect($expectedChain)->isNotEmpty(),
- 'The expected chain can not be empty.'
- );
-
- $this->isChainOfObjects($expectedChain)
- ? $this->assertPushedWithChainOfObjects($job, $expectedChain, $callback)
- : $this->assertPushedWithChainOfClasses($job, $expectedChain, $callback);
- }
-
- /**
- * Assert if a job was pushed with chained jobs based on a truth-test callback.
- *
- * @param string $job
- * @param array $expectedChain
- * @param callable|null $callback
- * @return void
- */
- protected function assertPushedWithChainOfObjects($job, $expectedChain, $callback)
- {
- $chain = collect($expectedChain)->map(function ($job) {
- return serialize($job);
- })->all();
-
- PHPUnit::assertTrue(
- $this->pushed($job, $callback)->filter(function ($job) use ($chain) {
- return $job->chained == $chain;
- })->isNotEmpty(),
- 'The expected chain was not pushed.'
- );
- }
-
- /**
- * Assert if a job was pushed with chained jobs based on a truth-test callback.
- *
- * @param string $job
- * @param array $expectedChain
- * @param callable|null $callback
- * @return void
- */
- protected function assertPushedWithChainOfClasses($job, $expectedChain, $callback)
- {
- $matching = $this->pushed($job, $callback)->map->chained->map(function ($chain) {
- return collect($chain)->map(function ($job) {
- return get_class(unserialize($job));
- });
- })->filter(function ($chain) use ($expectedChain) {
- return $chain->all() === $expectedChain;
- });
-
- PHPUnit::assertTrue(
- $matching->isNotEmpty(), 'The expected chain was not pushed.'
- );
- }
-
- /**
- * Determine if the given chain is entirely composed of objects.
- *
- * @param array $chain
- * @return bool
- */
- protected function isChainOfObjects($chain)
- {
- return ! collect($chain)->contains(function ($job) {
- return ! is_object($job);
- });
- }
-
- /**
- * Determine if a job was pushed based on a truth-test callback.
- *
- * @param string $job
- * @param callable|null $callback
- * @return void
- */
- public function assertNotPushed($job, $callback = null)
- {
- PHPUnit::assertTrue(
- $this->pushed($job, $callback)->count() === 0,
- "The unexpected [{$job}] job was pushed."
- );
- }
-
- /**
- * Assert that no jobs were pushed.
- *
- * @return void
- */
- public function assertNothingPushed()
- {
- PHPUnit::assertEmpty($this->jobs, 'Jobs were pushed unexpectedly.');
- }
-
- /**
- * Get all of the jobs matching a truth-test callback.
- *
- * @param string $job
- * @param callable|null $callback
- * @return \Illuminate\Support\Collection
- */
- public function pushed($job, $callback = null)
- {
- if (! $this->hasPushed($job)) {
- return collect();
- }
-
- $callback = $callback ?: function () {
- return true;
- };
-
- return collect($this->jobs[$job])->filter(function ($data) use ($callback) {
- return $callback($data['job'], $data['queue']);
- })->pluck('job');
- }
-
- /**
- * Determine if there are any stored jobs for a given class.
- *
- * @param string $job
- * @return bool
- */
- public function hasPushed($job)
- {
- return isset($this->jobs[$job]) && ! empty($this->jobs[$job]);
- }
-
- /**
- * Resolve a queue connection instance.
- *
- * @param mixed $value
- * @return \Illuminate\Contracts\Queue\Queue
- */
- public function connection($value = null)
- {
- return $this;
- }
-
- /**
- * Get the size of the queue.
- *
- * @param string|null $queue
- * @return int
- */
- public function size($queue = null)
- {
- return count($this->jobs);
- }
-
- /**
- * Push a new job onto the queue.
- *
- * @param string $job
- * @param mixed $data
- * @param string|null $queue
- * @return mixed
- */
- public function push($job, $data = '', $queue = null)
- {
- $this->jobs[is_object($job) ? get_class($job) : $job][] = [
- 'job' => $job,
- 'queue' => $queue,
- ];
- }
-
- /**
- * Push a raw payload onto the queue.
- *
- * @param string $payload
- * @param string|null $queue
- * @param array $options
- * @return mixed
- */
- public function pushRaw($payload, $queue = null, array $options = [])
- {
- //
- }
-
- /**
- * Push a new job onto the queue after a delay.
- *
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param string $job
- * @param mixed $data
- * @param string|null $queue
- * @return mixed
- */
- public function later($delay, $job, $data = '', $queue = null)
- {
- return $this->push($job, $data, $queue);
- }
-
- /**
- * Push a new job onto the queue.
- *
- * @param string $queue
- * @param string $job
- * @param mixed $data
- * @return mixed
- */
- public function pushOn($queue, $job, $data = '')
- {
- return $this->push($job, $data, $queue);
- }
-
- /**
- * Push a new job onto the queue after a delay.
- *
- * @param string $queue
- * @param \DateTimeInterface|\DateInterval|int $delay
- * @param string $job
- * @param mixed $data
- * @return mixed
- */
- public function laterOn($queue, $delay, $job, $data = '')
- {
- return $this->push($job, $data, $queue);
- }
-
- /**
- * Pop the next job off of the queue.
- *
- * @param string|null $queue
- * @return \Illuminate\Contracts\Queue\Job|null
- */
- public function pop($queue = null)
- {
- //
- }
-
- /**
- * Push an array of jobs onto the queue.
- *
- * @param array $jobs
- * @param mixed $data
- * @param string|null $queue
- * @return mixed
- */
- public function bulk($jobs, $data = '', $queue = null)
- {
- foreach ($jobs as $job) {
- $this->push($job, $data, $queue);
- }
- }
-
- /**
- * Get the jobs that have been pushed.
- *
- * @return array
- */
- public function pushedJobs()
- {
- return $this->jobs;
- }
-
- /**
- * Get the connection name for the queue.
- *
- * @return string
- */
- public function getConnectionName()
- {
- //
- }
-
- /**
- * Set the connection name for the queue.
- *
- * @param string $name
- * @return $this
- */
- public function setConnectionName($name)
- {
- return $this;
- }
-
- /**
- * Override the QueueManager to prevent circular dependency.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- throw new BadMethodCallException(sprintf(
- 'Call to undefined method %s::%s()', static::class, $method
- ));
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Traits;
-
-use Illuminate\Support\Fluent;
-use Illuminate\Contracts\Container\Container;
-
-trait CapsuleManagerTrait
-{
- /**
- * The current globally used instance.
- *
- * @var object
- */
- protected static $instance;
-
- /**
- * The container instance.
- *
- * @var \Illuminate\Contracts\Container\Container
- */
- protected $container;
-
- /**
- * Setup the IoC container instance.
- *
- * @param \Illuminate\Contracts\Container\Container $container
- * @return void
- */
- protected function setupContainer(Container $container)
- {
- $this->container = $container;
-
- if (! $this->container->bound('config')) {
- $this->container->instance('config', new Fluent);
- }
- }
-
- /**
- * Make this capsule instance available globally.
- *
- * @return void
- */
- public function setAsGlobal()
- {
- static::$instance = $this;
- }
-
- /**
- * Get the IoC container instance.
- *
- * @return \Illuminate\Contracts\Container\Container
- */
- public function getContainer()
- {
- return $this->container;
- }
-
- /**
- * Set the IoC container instance.
- *
- * @param \Illuminate\Contracts\Container\Container $container
- * @return void
- */
- public function setContainer(Container $container)
- {
- $this->container = $container;
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Traits;
-
-use Error;
-use BadMethodCallException;
-
-trait ForwardsCalls
-{
- /**
- * Forward a method call to the given object.
- *
- * @param mixed $object
- * @param string $method
- * @param array $parameters
- * @return mixed
- *
- * @throws \BadMethodCallException
- */
- protected function forwardCallTo($object, $method, $parameters)
- {
- try {
- return $object->{$method}(...$parameters);
- } catch (Error | BadMethodCallException $e) {
- $pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
-
- if (! preg_match($pattern, $e->getMessage(), $matches)) {
- throw $e;
- }
-
- if ($matches['class'] != get_class($object) ||
- $matches['method'] != $method) {
- throw $e;
- }
-
- static::throwBadMethodCallException($method);
- }
- }
-
- /**
- * Throw a bad method call exception for the given method.
- *
- * @param string $method
- * @return void
- *
- * @throws \BadMethodCallException
- */
- protected static function throwBadMethodCallException($method)
- {
- throw new BadMethodCallException(sprintf(
- 'Call to undefined method %s::%s()', static::class, $method
- ));
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Traits;
-
-use Illuminate\Container\Container;
-
-trait Localizable
-{
- /**
- * Run the callback with the given locale.
- *
- * @param string $locale
- * @param \Closure $callback
- * @return mixed
- */
- public function withLocale($locale, $callback)
- {
- if (! $locale) {
- return $callback();
- }
-
- $app = Container::getInstance();
-
- $original = $app->getLocale();
-
- try {
- $app->setLocale($locale);
-
- return $callback();
- } finally {
- $app->setLocale($original);
- }
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Traits;
-
-use Closure;
-use ReflectionClass;
-use ReflectionMethod;
-use BadMethodCallException;
-
-trait Macroable
-{
- /**
- * The registered string macros.
- *
- * @var array
- */
- protected static $macros = [];
-
- /**
- * Register a custom macro.
- *
- * @param string $name
- * @param object|callable $macro
- *
- * @return void
- */
- public static function macro($name, $macro)
- {
- static::$macros[$name] = $macro;
- }
-
- /**
- * Mix another object into the class.
- *
- * @param object $mixin
- * @param bool $replace
- * @return void
- *
- * @throws \ReflectionException
- */
- public static function mixin($mixin, $replace = true)
- {
- $methods = (new ReflectionClass($mixin))->getMethods(
- ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
- );
-
- foreach ($methods as $method) {
- if ($replace || ! static::hasMacro($method->name)) {
- $method->setAccessible(true);
- static::macro($method->name, $method->invoke($mixin));
- }
- }
- }
-
- /**
- * Checks if macro is registered.
- *
- * @param string $name
- * @return bool
- */
- public static function hasMacro($name)
- {
- return isset(static::$macros[$name]);
- }
-
- /**
- * Dynamically handle calls to the class.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- *
- * @throws \BadMethodCallException
- */
- public static function __callStatic($method, $parameters)
- {
- if (! static::hasMacro($method)) {
- throw new BadMethodCallException(sprintf(
- 'Method %s::%s does not exist.', static::class, $method
- ));
- }
-
- if (static::$macros[$method] instanceof Closure) {
- return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
- }
-
- return call_user_func_array(static::$macros[$method], $parameters);
- }
-
- /**
- * Dynamically handle calls to the class.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- *
- * @throws \BadMethodCallException
- */
- public function __call($method, $parameters)
- {
- if (! static::hasMacro($method)) {
- throw new BadMethodCallException(sprintf(
- 'Method %s::%s does not exist.', static::class, $method
- ));
- }
-
- $macro = static::$macros[$method];
-
- if ($macro instanceof Closure) {
- return call_user_func_array($macro->bindTo($this, static::class), $parameters);
- }
-
- return call_user_func_array($macro, $parameters);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support\Traits;
-
-trait Tappable
-{
- /**
- * Call the given Closure with this instance then return the instance.
- *
- * @param callable|null $callback
- * @return mixed
- */
- public function tap($callback = null)
- {
- return tap($this, $callback);
- }
-}
+++ /dev/null
-<?php
-
-namespace Illuminate\Support;
-
-use Countable;
-use Illuminate\Contracts\Support\MessageBag as MessageBagContract;
-
-/**
- * @mixin \Illuminate\Contracts\Support\MessageBag
- */
-class ViewErrorBag implements Countable
-{
- /**
- * The array of the view error bags.
- *
- * @var array
- */
- protected $bags = [];
-
- /**
- * Checks if a named MessageBag exists in the bags.
- *
- * @param string $key
- * @return bool
- */
- public function hasBag($key = 'default')
- {
- return isset($this->bags[$key]);
- }
-
- /**
- * Get a MessageBag instance from the bags.
- *
- * @param string $key
- * @return \Illuminate\Contracts\Support\MessageBag
- */
- public function getBag($key)
- {
- return Arr::get($this->bags, $key) ?: new MessageBag;
- }
-
- /**
- * Get all the bags.
- *
- * @return array
- */
- public function getBags()
- {
- return $this->bags;
- }
-
- /**
- * Add a new MessageBag instance to the bags.
- *
- * @param string $key
- * @param \Illuminate\Contracts\Support\MessageBag $bag
- * @return $this
- */
- public function put($key, MessageBagContract $bag)
- {
- $this->bags[$key] = $bag;
-
- return $this;
- }
-
- /**
- * Determine if the default message bag has any messages.
- *
- * @return bool
- */
- public function any()
- {
- return $this->count() > 0;
- }
-
- /**
- * Get the number of messages in the default bag.
- *
- * @return int
- */
- public function count()
- {
- return $this->getBag('default')->count();
- }
-
- /**
- * Dynamically call methods on the default bag.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- return $this->getBag('default')->$method(...$parameters);
- }
-
- /**
- * Dynamically access a view error bag.
- *
- * @param string $key
- * @return \Illuminate\Contracts\Support\MessageBag
- */
- public function __get($key)
- {
- return $this->getBag($key);
- }
-
- /**
- * Dynamically set a view error bag.
- *
- * @param string $key
- * @param \Illuminate\Contracts\Support\MessageBag $value
- * @return void
- */
- public function __set($key, $value)
- {
- $this->put($key, $value);
- }
-
- /**
- * Convert the default bag to its string representation.
- *
- * @return string
- */
- public function __toString()
- {
- return (string) $this->getBag('default');
- }
-}
+++ /dev/null
-{
- "name": "illuminate/support",
- "description": "The Illuminate Support package.",
- "license": "MIT",
- "homepage": "https://laravel.com",
- "support": {
- "issues": "https://github.com/laravel/framework/issues",
- "source": "https://github.com/laravel/framework"
- },
- "authors": [
- {
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
- }
- ],
- "require": {
- "php": "^7.1.3",
- "ext-json": "*",
- "ext-mbstring": "*",
- "doctrine/inflector": "^1.1",
- "illuminate/contracts": "5.8.*",
- "nesbot/carbon": "^1.26.3 || ^2.0"
- },
- "conflict": {
- "tightenco/collect": "<5.5.33"
- },
- "autoload": {
- "psr-4": {
- "Illuminate\\Support\\": ""
- },
- "files": [
- "helpers.php"
- ]
- },
- "extra": {
- "branch-alias": {
- "dev-master": "5.8-dev"
- }
- },
- "suggest": {
- "illuminate/filesystem": "Required to use the composer class (5.8.*).",
- "moontoast/math": "Required to use ordered UUIDs (^1.1).",
- "ramsey/uuid": "Required to use Str::uuid() (^3.7).",
- "symfony/process": "Required to use the composer class (^4.2).",
- "symfony/var-dumper": "Required to use the dd function (^4.2).",
- "vlucas/phpdotenv": "Required to use the env helper (^3.3)."
- },
- "config": {
- "sort-packages": true
- },
- "minimum-stability": "dev"
-}
+++ /dev/null
-<?php
-
-use PhpOption\Option;
-use Illuminate\Support\Arr;
-use Illuminate\Support\Str;
-use Illuminate\Support\Optional;
-use Illuminate\Support\Collection;
-use Dotenv\Environment\DotenvFactory;
-use Illuminate\Contracts\Support\Htmlable;
-use Illuminate\Support\HigherOrderTapProxy;
-use Dotenv\Environment\Adapter\PutenvAdapter;
-use Dotenv\Environment\Adapter\EnvConstAdapter;
-use Dotenv\Environment\Adapter\ServerConstAdapter;
-
-if (! function_exists('append_config')) {
- /**
- * Assign high numeric IDs to a config item to force appending.
- *
- * @param array $array
- * @return array
- */
- function append_config(array $array)
- {
- $start = 9999;
-
- foreach ($array as $key => $value) {
- if (is_numeric($key)) {
- $start++;
-
- $array[$start] = Arr::pull($array, $key);
- }
- }
-
- return $array;
- }
-}
-
-if (! function_exists('array_add')) {
- /**
- * Add an element to an array using "dot" notation if it doesn't exist.
- *
- * @param array $array
- * @param string $key
- * @param mixed $value
- * @return array
- *
- * @deprecated Arr::add() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_add($array, $key, $value)
- {
- return Arr::add($array, $key, $value);
- }
-}
-
-if (! function_exists('array_collapse')) {
- /**
- * Collapse an array of arrays into a single array.
- *
- * @param array $array
- * @return array
- *
- * @deprecated Arr::collapse() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_collapse($array)
- {
- return Arr::collapse($array);
- }
-}
-
-if (! function_exists('array_divide')) {
- /**
- * Divide an array into two arrays. One with keys and the other with values.
- *
- * @param array $array
- * @return array
- *
- * @deprecated Arr::divide() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_divide($array)
- {
- return Arr::divide($array);
- }
-}
-
-if (! function_exists('array_dot')) {
- /**
- * Flatten a multi-dimensional associative array with dots.
- *
- * @param array $array
- * @param string $prepend
- * @return array
- *
- * @deprecated Arr::dot() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_dot($array, $prepend = '')
- {
- return Arr::dot($array, $prepend);
- }
-}
-
-if (! function_exists('array_except')) {
- /**
- * Get all of the given array except for a specified array of keys.
- *
- * @param array $array
- * @param array|string $keys
- * @return array
- *
- * @deprecated Arr::except() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_except($array, $keys)
- {
- return Arr::except($array, $keys);
- }
-}
-
-if (! function_exists('array_first')) {
- /**
- * Return the first element in an array passing a given truth test.
- *
- * @param array $array
- * @param callable|null $callback
- * @param mixed $default
- * @return mixed
- *
- * @deprecated Arr::first() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_first($array, callable $callback = null, $default = null)
- {
- return Arr::first($array, $callback, $default);
- }
-}
-
-if (! function_exists('array_flatten')) {
- /**
- * Flatten a multi-dimensional array into a single level.
- *
- * @param array $array
- * @param int $depth
- * @return array
- *
- * @deprecated Arr::flatten() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_flatten($array, $depth = INF)
- {
- return Arr::flatten($array, $depth);
- }
-}
-
-if (! function_exists('array_forget')) {
- /**
- * Remove one or many array items from a given array using "dot" notation.
- *
- * @param array $array
- * @param array|string $keys
- * @return void
- *
- * @deprecated Arr::forget() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_forget(&$array, $keys)
- {
- return Arr::forget($array, $keys);
- }
-}
-
-if (! function_exists('array_get')) {
- /**
- * Get an item from an array using "dot" notation.
- *
- * @param \ArrayAccess|array $array
- * @param string $key
- * @param mixed $default
- * @return mixed
- *
- * @deprecated Arr::get() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_get($array, $key, $default = null)
- {
- return Arr::get($array, $key, $default);
- }
-}
-
-if (! function_exists('array_has')) {
- /**
- * Check if an item or items exist in an array using "dot" notation.
- *
- * @param \ArrayAccess|array $array
- * @param string|array $keys
- * @return bool
- *
- * @deprecated Arr::has() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_has($array, $keys)
- {
- return Arr::has($array, $keys);
- }
-}
-
-if (! function_exists('array_last')) {
- /**
- * Return the last element in an array passing a given truth test.
- *
- * @param array $array
- * @param callable|null $callback
- * @param mixed $default
- * @return mixed
- *
- * @deprecated Arr::last() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_last($array, callable $callback = null, $default = null)
- {
- return Arr::last($array, $callback, $default);
- }
-}
-
-if (! function_exists('array_only')) {
- /**
- * Get a subset of the items from the given array.
- *
- * @param array $array
- * @param array|string $keys
- * @return array
- *
- * @deprecated Arr::only() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_only($array, $keys)
- {
- return Arr::only($array, $keys);
- }
-}
-
-if (! function_exists('array_pluck')) {
- /**
- * Pluck an array of values from an array.
- *
- * @param array $array
- * @param string|array $value
- * @param string|array|null $key
- * @return array
- *
- * @deprecated Arr::pluck() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_pluck($array, $value, $key = null)
- {
- return Arr::pluck($array, $value, $key);
- }
-}
-
-if (! function_exists('array_prepend')) {
- /**
- * Push an item onto the beginning of an array.
- *
- * @param array $array
- * @param mixed $value
- * @param mixed $key
- * @return array
- *
- * @deprecated Arr::prepend() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_prepend($array, $value, $key = null)
- {
- return Arr::prepend($array, $value, $key);
- }
-}
-
-if (! function_exists('array_pull')) {
- /**
- * Get a value from the array, and remove it.
- *
- * @param array $array
- * @param string $key
- * @param mixed $default
- * @return mixed
- *
- * @deprecated Arr::pull() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_pull(&$array, $key, $default = null)
- {
- return Arr::pull($array, $key, $default);
- }
-}
-
-if (! function_exists('array_random')) {
- /**
- * Get a random value from an array.
- *
- * @param array $array
- * @param int|null $num
- * @return mixed
- *
- * @deprecated Arr::random() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_random($array, $num = null)
- {
- return Arr::random($array, $num);
- }
-}
-
-if (! function_exists('array_set')) {
- /**
- * Set an array item to a given value using "dot" notation.
- *
- * If no key is given to the method, the entire array will be replaced.
- *
- * @param array $array
- * @param string $key
- * @param mixed $value
- * @return array
- *
- * @deprecated Arr::set() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_set(&$array, $key, $value)
- {
- return Arr::set($array, $key, $value);
- }
-}
-
-if (! function_exists('array_sort')) {
- /**
- * Sort the array by the given callback or attribute name.
- *
- * @param array $array
- * @param callable|string|null $callback
- * @return array
- *
- * @deprecated Arr::sort() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_sort($array, $callback = null)
- {
- return Arr::sort($array, $callback);
- }
-}
-
-if (! function_exists('array_sort_recursive')) {
- /**
- * Recursively sort an array by keys and values.
- *
- * @param array $array
- * @return array
- *
- * @deprecated Arr::sortRecursive() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_sort_recursive($array)
- {
- return Arr::sortRecursive($array);
- }
-}
-
-if (! function_exists('array_where')) {
- /**
- * Filter the array using the given callback.
- *
- * @param array $array
- * @param callable $callback
- * @return array
- *
- * @deprecated Arr::where() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_where($array, callable $callback)
- {
- return Arr::where($array, $callback);
- }
-}
-
-if (! function_exists('array_wrap')) {
- /**
- * If the given value is not an array, wrap it in one.
- *
- * @param mixed $value
- * @return array
- *
- * @deprecated Arr::wrap() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function array_wrap($value)
- {
- return Arr::wrap($value);
- }
-}
-
-if (! function_exists('blank')) {
- /**
- * Determine if the given value is "blank".
- *
- * @param mixed $value
- * @return bool
- */
- function blank($value)
- {
- if (is_null($value)) {
- return true;
- }
-
- if (is_string($value)) {
- return trim($value) === '';
- }
-
- if (is_numeric($value) || is_bool($value)) {
- return false;
- }
-
- if ($value instanceof Countable) {
- return count($value) === 0;
- }
-
- return empty($value);
- }
-}
-
-if (! function_exists('camel_case')) {
- /**
- * Convert a value to camel case.
- *
- * @param string $value
- * @return string
- *
- * @deprecated Str::camel() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function camel_case($value)
- {
- return Str::camel($value);
- }
-}
-
-if (! function_exists('class_basename')) {
- /**
- * Get the class "basename" of the given object / class.
- *
- * @param string|object $class
- * @return string
- */
- function class_basename($class)
- {
- $class = is_object($class) ? get_class($class) : $class;
-
- return basename(str_replace('\\', '/', $class));
- }
-}
-
-if (! function_exists('class_uses_recursive')) {
- /**
- * Returns all traits used by a class, its parent classes and trait of their traits.
- *
- * @param object|string $class
- * @return array
- */
- function class_uses_recursive($class)
- {
- if (is_object($class)) {
- $class = get_class($class);
- }
-
- $results = [];
-
- foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) {
- $results += trait_uses_recursive($class);
- }
-
- return array_unique($results);
- }
-}
-
-if (! function_exists('collect')) {
- /**
- * Create a collection from the given value.
- *
- * @param mixed $value
- * @return \Illuminate\Support\Collection
- */
- function collect($value = null)
- {
- return new Collection($value);
- }
-}
-
-if (! function_exists('data_fill')) {
- /**
- * Fill in data where it's missing.
- *
- * @param mixed $target
- * @param string|array $key
- * @param mixed $value
- * @return mixed
- */
- function data_fill(&$target, $key, $value)
- {
- return data_set($target, $key, $value, false);
- }
-}
-
-if (! function_exists('data_get')) {
- /**
- * Get an item from an array or object using "dot" notation.
- *
- * @param mixed $target
- * @param string|array|int $key
- * @param mixed $default
- * @return mixed
- */
- function data_get($target, $key, $default = null)
- {
- if (is_null($key)) {
- return $target;
- }
-
- $key = is_array($key) ? $key : explode('.', $key);
-
- while (! is_null($segment = array_shift($key))) {
- if ($segment === '*') {
- if ($target instanceof Collection) {
- $target = $target->all();
- } elseif (! is_array($target)) {
- return value($default);
- }
-
- $result = [];
-
- foreach ($target as $item) {
- $result[] = data_get($item, $key);
- }
-
- return in_array('*', $key) ? Arr::collapse($result) : $result;
- }
-
- if (Arr::accessible($target) && Arr::exists($target, $segment)) {
- $target = $target[$segment];
- } elseif (is_object($target) && isset($target->{$segment})) {
- $target = $target->{$segment};
- } else {
- return value($default);
- }
- }
-
- return $target;
- }
-}
-
-if (! function_exists('data_set')) {
- /**
- * Set an item on an array or object using dot notation.
- *
- * @param mixed $target
- * @param string|array $key
- * @param mixed $value
- * @param bool $overwrite
- * @return mixed
- */
- function data_set(&$target, $key, $value, $overwrite = true)
- {
- $segments = is_array($key) ? $key : explode('.', $key);
-
- if (($segment = array_shift($segments)) === '*') {
- if (! Arr::accessible($target)) {
- $target = [];
- }
-
- if ($segments) {
- foreach ($target as &$inner) {
- data_set($inner, $segments, $value, $overwrite);
- }
- } elseif ($overwrite) {
- foreach ($target as &$inner) {
- $inner = $value;
- }
- }
- } elseif (Arr::accessible($target)) {
- if ($segments) {
- if (! Arr::exists($target, $segment)) {
- $target[$segment] = [];
- }
-
- data_set($target[$segment], $segments, $value, $overwrite);
- } elseif ($overwrite || ! Arr::exists($target, $segment)) {
- $target[$segment] = $value;
- }
- } elseif (is_object($target)) {
- if ($segments) {
- if (! isset($target->{$segment})) {
- $target->{$segment} = [];
- }
-
- data_set($target->{$segment}, $segments, $value, $overwrite);
- } elseif ($overwrite || ! isset($target->{$segment})) {
- $target->{$segment} = $value;
- }
- } else {
- $target = [];
-
- if ($segments) {
- data_set($target[$segment], $segments, $value, $overwrite);
- } elseif ($overwrite) {
- $target[$segment] = $value;
- }
- }
-
- return $target;
- }
-}
-
-if (! function_exists('e')) {
- /**
- * Encode HTML special characters in a string.
- *
- * @param \Illuminate\Contracts\Support\Htmlable|string $value
- * @param bool $doubleEncode
- * @return string
- */
- function e($value, $doubleEncode = true)
- {
- if ($value instanceof Htmlable) {
- return $value->toHtml();
- }
-
- return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', $doubleEncode);
- }
-}
-
-if (! function_exists('ends_with')) {
- /**
- * Determine if a given string ends with a given substring.
- *
- * @param string $haystack
- * @param string|array $needles
- * @return bool
- *
- * @deprecated Str::endsWith() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function ends_with($haystack, $needles)
- {
- return Str::endsWith($haystack, $needles);
- }
-}
-
-if (! function_exists('env')) {
- /**
- * Gets the value of an environment variable.
- *
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- function env($key, $default = null)
- {
- static $variables;
-
- if ($variables === null) {
- $variables = (new DotenvFactory([new EnvConstAdapter, new PutenvAdapter, new ServerConstAdapter]))->createImmutable();
- }
-
- return Option::fromValue($variables->get($key))
- ->map(function ($value) {
- switch (strtolower($value)) {
- case 'true':
- case '(true)':
- return true;
- case 'false':
- case '(false)':
- return false;
- case 'empty':
- case '(empty)':
- return '';
- case 'null':
- case '(null)':
- return;
- }
-
- if (preg_match('/\A([\'"])(.*)\1\z/', $value, $matches)) {
- return $matches[2];
- }
-
- return $value;
- })
- ->getOrCall(function () use ($default) {
- return value($default);
- });
- }
-}
-
-if (! function_exists('filled')) {
- /**
- * Determine if a value is "filled".
- *
- * @param mixed $value
- * @return bool
- */
- function filled($value)
- {
- return ! blank($value);
- }
-}
-
-if (! function_exists('head')) {
- /**
- * Get the first element of an array. Useful for method chaining.
- *
- * @param array $array
- * @return mixed
- */
- function head($array)
- {
- return reset($array);
- }
-}
-
-if (! function_exists('kebab_case')) {
- /**
- * Convert a string to kebab case.
- *
- * @param string $value
- * @return string
- *
- * @deprecated Str::kebab() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function kebab_case($value)
- {
- return Str::kebab($value);
- }
-}
-
-if (! function_exists('last')) {
- /**
- * Get the last element from an array.
- *
- * @param array $array
- * @return mixed
- */
- function last($array)
- {
- return end($array);
- }
-}
-
-if (! function_exists('object_get')) {
- /**
- * Get an item from an object using "dot" notation.
- *
- * @param object $object
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- function object_get($object, $key, $default = null)
- {
- if (is_null($key) || trim($key) == '') {
- return $object;
- }
-
- foreach (explode('.', $key) as $segment) {
- if (! is_object($object) || ! isset($object->{$segment})) {
- return value($default);
- }
-
- $object = $object->{$segment};
- }
-
- return $object;
- }
-}
-
-if (! function_exists('optional')) {
- /**
- * Provide access to optional objects.
- *
- * @param mixed $value
- * @param callable|null $callback
- * @return mixed
- */
- function optional($value = null, callable $callback = null)
- {
- if (is_null($callback)) {
- return new Optional($value);
- } elseif (! is_null($value)) {
- return $callback($value);
- }
- }
-}
-
-if (! function_exists('preg_replace_array')) {
- /**
- * Replace a given pattern with each value in the array in sequentially.
- *
- * @param string $pattern
- * @param array $replacements
- * @param string $subject
- * @return string
- */
- function preg_replace_array($pattern, array $replacements, $subject)
- {
- return preg_replace_callback($pattern, function () use (&$replacements) {
- foreach ($replacements as $key => $value) {
- return array_shift($replacements);
- }
- }, $subject);
- }
-}
-
-if (! function_exists('retry')) {
- /**
- * Retry an operation a given number of times.
- *
- * @param int $times
- * @param callable $callback
- * @param int $sleep
- * @param callable $when
- * @return mixed
- *
- * @throws \Exception
- */
- function retry($times, callable $callback, $sleep = 0, $when = null)
- {
- $attempts = 0;
- $times--;
-
- beginning:
- $attempts++;
-
- try {
- return $callback($attempts);
- } catch (Exception $e) {
- if (! $times || ($when && ! $when($e))) {
- throw $e;
- }
-
- $times--;
-
- if ($sleep) {
- usleep($sleep * 1000);
- }
-
- goto beginning;
- }
- }
-}
-
-if (! function_exists('snake_case')) {
- /**
- * Convert a string to snake case.
- *
- * @param string $value
- * @param string $delimiter
- * @return string
- *
- * @deprecated Str::snake() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function snake_case($value, $delimiter = '_')
- {
- return Str::snake($value, $delimiter);
- }
-}
-
-if (! function_exists('starts_with')) {
- /**
- * Determine if a given string starts with a given substring.
- *
- * @param string $haystack
- * @param string|array $needles
- * @return bool
- *
- * @deprecated Str::startsWith() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function starts_with($haystack, $needles)
- {
- return Str::startsWith($haystack, $needles);
- }
-}
-
-if (! function_exists('str_after')) {
- /**
- * Return the remainder of a string after a given value.
- *
- * @param string $subject
- * @param string $search
- * @return string
- *
- * @deprecated Str::after() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_after($subject, $search)
- {
- return Str::after($subject, $search);
- }
-}
-
-if (! function_exists('str_before')) {
- /**
- * Get the portion of a string before a given value.
- *
- * @param string $subject
- * @param string $search
- * @return string
- *
- * @deprecated Str::before() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_before($subject, $search)
- {
- return Str::before($subject, $search);
- }
-}
-
-if (! function_exists('str_contains')) {
- /**
- * Determine if a given string contains a given substring.
- *
- * @param string $haystack
- * @param string|array $needles
- * @return bool
- *
- * @deprecated Str::contains() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_contains($haystack, $needles)
- {
- return Str::contains($haystack, $needles);
- }
-}
-
-if (! function_exists('str_finish')) {
- /**
- * Cap a string with a single instance of a given value.
- *
- * @param string $value
- * @param string $cap
- * @return string
- *
- * @deprecated Str::finish() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_finish($value, $cap)
- {
- return Str::finish($value, $cap);
- }
-}
-
-if (! function_exists('str_is')) {
- /**
- * Determine if a given string matches a given pattern.
- *
- * @param string|array $pattern
- * @param string $value
- * @return bool
- *
- * @deprecated Str::is() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_is($pattern, $value)
- {
- return Str::is($pattern, $value);
- }
-}
-
-if (! function_exists('str_limit')) {
- /**
- * Limit the number of characters in a string.
- *
- * @param string $value
- * @param int $limit
- * @param string $end
- * @return string
- *
- * @deprecated Str::limit() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_limit($value, $limit = 100, $end = '...')
- {
- return Str::limit($value, $limit, $end);
- }
-}
-
-if (! function_exists('str_plural')) {
- /**
- * Get the plural form of an English word.
- *
- * @param string $value
- * @param int $count
- * @return string
- *
- * @deprecated Str::plural() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_plural($value, $count = 2)
- {
- return Str::plural($value, $count);
- }
-}
-
-if (! function_exists('str_random')) {
- /**
- * Generate a more truly "random" alpha-numeric string.
- *
- * @param int $length
- * @return string
- *
- * @throws \RuntimeException
- *
- * @deprecated Str::random() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_random($length = 16)
- {
- return Str::random($length);
- }
-}
-
-if (! function_exists('str_replace_array')) {
- /**
- * Replace a given value in the string sequentially with an array.
- *
- * @param string $search
- * @param array $replace
- * @param string $subject
- * @return string
- *
- * @deprecated Str::replaceArray() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_replace_array($search, array $replace, $subject)
- {
- return Str::replaceArray($search, $replace, $subject);
- }
-}
-
-if (! function_exists('str_replace_first')) {
- /**
- * Replace the first occurrence of a given value in the string.
- *
- * @param string $search
- * @param string $replace
- * @param string $subject
- * @return string
- *
- * @deprecated Str::replaceFirst() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_replace_first($search, $replace, $subject)
- {
- return Str::replaceFirst($search, $replace, $subject);
- }
-}
-
-if (! function_exists('str_replace_last')) {
- /**
- * Replace the last occurrence of a given value in the string.
- *
- * @param string $search
- * @param string $replace
- * @param string $subject
- * @return string
- *
- * @deprecated Str::replaceLast() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_replace_last($search, $replace, $subject)
- {
- return Str::replaceLast($search, $replace, $subject);
- }
-}
-
-if (! function_exists('str_singular')) {
- /**
- * Get the singular form of an English word.
- *
- * @param string $value
- * @return string
- *
- * @deprecated Str::singular() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_singular($value)
- {
- return Str::singular($value);
- }
-}
-
-if (! function_exists('str_slug')) {
- /**
- * Generate a URL friendly "slug" from a given string.
- *
- * @param string $title
- * @param string $separator
- * @param string $language
- * @return string
- *
- * @deprecated Str::slug() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_slug($title, $separator = '-', $language = 'en')
- {
- return Str::slug($title, $separator, $language);
- }
-}
-
-if (! function_exists('str_start')) {
- /**
- * Begin a string with a single instance of a given value.
- *
- * @param string $value
- * @param string $prefix
- * @return string
- *
- * @deprecated Str::start() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function str_start($value, $prefix)
- {
- return Str::start($value, $prefix);
- }
-}
-
-if (! function_exists('studly_case')) {
- /**
- * Convert a value to studly caps case.
- *
- * @param string $value
- * @return string
- *
- * @deprecated Str::studly() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function studly_case($value)
- {
- return Str::studly($value);
- }
-}
-
-if (! function_exists('tap')) {
- /**
- * Call the given Closure with the given value then return the value.
- *
- * @param mixed $value
- * @param callable|null $callback
- * @return mixed
- */
- function tap($value, $callback = null)
- {
- if (is_null($callback)) {
- return new HigherOrderTapProxy($value);
- }
-
- $callback($value);
-
- return $value;
- }
-}
-
-if (! function_exists('throw_if')) {
- /**
- * Throw the given exception if the given condition is true.
- *
- * @param mixed $condition
- * @param \Throwable|string $exception
- * @param array ...$parameters
- * @return mixed
- *
- * @throws \Throwable
- */
- function throw_if($condition, $exception, ...$parameters)
- {
- if ($condition) {
- throw (is_string($exception) ? new $exception(...$parameters) : $exception);
- }
-
- return $condition;
- }
-}
-
-if (! function_exists('throw_unless')) {
- /**
- * Throw the given exception unless the given condition is true.
- *
- * @param mixed $condition
- * @param \Throwable|string $exception
- * @param array ...$parameters
- * @return mixed
- * @throws \Throwable
- */
- function throw_unless($condition, $exception, ...$parameters)
- {
- if (! $condition) {
- throw (is_string($exception) ? new $exception(...$parameters) : $exception);
- }
-
- return $condition;
- }
-}
-
-if (! function_exists('title_case')) {
- /**
- * Convert a value to title case.
- *
- * @param string $value
- * @return string
- *
- * @deprecated Str::title() should be used directly instead. Will be removed in Laravel 5.9.
- */
- function title_case($value)
- {
- return Str::title($value);
- }
-}
-
-if (! function_exists('trait_uses_recursive')) {
- /**
- * Returns all traits used by a trait and its traits.
- *
- * @param string $trait
- * @return array
- */
- function trait_uses_recursive($trait)
- {
- $traits = class_uses($trait);
-
- foreach ($traits as $trait) {
- $traits += trait_uses_recursive($trait);
- }
-
- return $traits;
- }
-}
-
-if (! function_exists('transform')) {
- /**
- * Transform the given value if it is present.
- *
- * @param mixed $value
- * @param callable $callback
- * @param mixed $default
- * @return mixed|null
- */
- function transform($value, callable $callback, $default = null)
- {
- if (filled($value)) {
- return $callback($value);
- }
-
- if (is_callable($default)) {
- return $default($value);
- }
-
- return $default;
- }
-}
-
-if (! function_exists('value')) {
- /**
- * Return the default value of the given value.
- *
- * @param mixed $value
- * @return mixed
- */
- function value($value)
- {
- return $value instanceof Closure ? $value() : $value;
- }
-}
-
-if (! function_exists('windows_os')) {
- /**
- * Determine whether the current environment is Windows based.
- *
- * @return bool
- */
- function windows_os()
- {
- return strtolower(substr(PHP_OS, 0, 3)) === 'win';
- }
-}
-
-if (! function_exists('with')) {
- /**
- * Return the given value, optionally passed through the given callback.
- *
- * @param mixed $value
- * @param callable|null $callback
- * @return mixed
- */
- function with($value, callable $callback = null)
- {
- return is_null($callback) ? $value : $callback($value);
- }
-}
--- /dev/null
+*~
+/composer.lock
+/vendor/
--- /dev/null
+PHP Markdown Lib
+Copyright (c) 2004-2018 Michel Fortin
+<https://michelf.ca/>
+All rights reserved.
+
+Based on Markdown
+Copyright (c) 2003-2006 John Gruber
+<https://daringfireball.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.
+
+* Neither the name "Markdown" nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as
+is" and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed. In no event shall the copyright 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.
--- /dev/null
+<?php
+
+// Use this file if you cannot use class autoloading. It will include all the
+// files needed for the Markdown parser.
+//
+// Take a look at the PSR-0-compatible class autoloading implementation
+// in the Readme.php file if you want a simple autoloader setup.
+
+require_once dirname(__FILE__) . '/MarkdownInterface.php';
+require_once dirname(__FILE__) . '/Markdown.php';
--- /dev/null
+<?php
+/**
+ * Markdown - A text-to-HTML conversion tool for web writers
+ *
+ * @package php-markdown
+ * @author Michel Fortin <michel.fortin@michelf.com>
+ * @copyright 2004-2018 Michel Fortin <https://michelf.com/projects/php-markdown/>
+ * @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
+ */
+
+namespace Michelf;
+
+/**
+ * Markdown Parser Class
+ */
+class Markdown implements MarkdownInterface {
+ /**
+ * Define the package version
+ * @var string
+ */
+ const MARKDOWNLIB_VERSION = "1.8.0";
+
+ /**
+ * Simple function interface - Initialize the parser and return the result
+ * of its transform method. This will work fine for derived classes too.
+ *
+ * @api
+ *
+ * @param string $text
+ * @return string
+ */
+ public static function defaultTransform($text) {
+ // Take parser class on which this function was called.
+ $parser_class = \get_called_class();
+
+ // Try to take parser from the static parser list
+ static $parser_list;
+ $parser =& $parser_list[$parser_class];
+
+ // Create the parser it not already set
+ if (!$parser) {
+ $parser = new $parser_class;
+ }
+
+ // Transform text using parser.
+ return $parser->transform($text);
+ }
+
+ /**
+ * Configuration variables
+ */
+
+ /**
+ * Change to ">" for HTML output.
+ * @var string
+ */
+ public $empty_element_suffix = " />";
+
+ /**
+ * The width of indentation of the output markup
+ * @var int
+ */
+ public $tab_width = 4;
+
+ /**
+ * Change to `true` to disallow markup or entities.
+ * @var boolean
+ */
+ public $no_markup = false;
+ public $no_entities = false;
+
+
+ /**
+ * Change to `true` to enable line breaks on \n without two trailling spaces
+ * @var boolean
+ */
+ public $hard_wrap = false;
+
+ /**
+ * Predefined URLs and titles for reference links and images.
+ * @var array
+ */
+ public $predef_urls = array();
+ public $predef_titles = array();
+
+ /**
+ * Optional filter function for URLs
+ * @var callable
+ */
+ public $url_filter_func = null;
+
+ /**
+ * Optional header id="" generation callback function.
+ * @var callable
+ */
+ public $header_id_func = null;
+
+ /**
+ * Optional function for converting code block content to HTML
+ * @var callable
+ */
+ public $code_block_content_func = null;
+
+ /**
+ * Optional function for converting code span content to HTML.
+ * @var callable
+ */
+ public $code_span_content_func = null;
+
+ /**
+ * Class attribute to toggle "enhanced ordered list" behaviour
+ * setting this to true will allow ordered lists to start from the index
+ * number that is defined first.
+ *
+ * For example:
+ * 2. List item two
+ * 3. List item three
+ *
+ * Becomes:
+ * <ol start="2">
+ * <li>List item two</li>
+ * <li>List item three</li>
+ * </ol>
+ *
+ * @var bool
+ */
+ public $enhanced_ordered_list = false;
+
+ /**
+ * Parser implementation
+ */
+
+ /**
+ * Regex to match balanced [brackets].
+ * Needed to insert a maximum bracked depth while converting to PHP.
+ * @var int
+ */
+ protected $nested_brackets_depth = 6;
+ protected $nested_brackets_re;
+
+ protected $nested_url_parenthesis_depth = 4;
+ protected $nested_url_parenthesis_re;
+
+ /**
+ * Table of hash values for escaped characters:
+ * @var string
+ */
+ protected $escape_chars = '\`*_{}[]()>#+-.!';
+ protected $escape_chars_re;
+
+ /**
+ * Constructor function. Initialize appropriate member variables.
+ * @return void
+ */
+ public function __construct() {
+ $this->_initDetab();
+ $this->prepareItalicsAndBold();
+
+ $this->nested_brackets_re =
+ str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
+ str_repeat('\])*', $this->nested_brackets_depth);
+
+ $this->nested_url_parenthesis_re =
+ str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
+ str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
+
+ $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
+
+ // Sort document, block, and span gamut in ascendent priority order.
+ asort($this->document_gamut);
+ asort($this->block_gamut);
+ asort($this->span_gamut);
+ }
+
+
+ /**
+ * Internal hashes used during transformation.
+ * @var array
+ */
+ protected $urls = array();
+ protected $titles = array();
+ protected $html_hashes = array();
+
+ /**
+ * Status flag to avoid invalid nesting.
+ * @var boolean
+ */
+ protected $in_anchor = false;
+
+ /**
+ * Status flag to avoid invalid nesting.
+ * @var boolean
+ */
+ protected $in_emphasis_processing = false;
+
+ /**
+ * Called before the transformation process starts to setup parser states.
+ * @return void
+ */
+ protected function setup() {
+ // Clear global hashes.
+ $this->urls = $this->predef_urls;
+ $this->titles = $this->predef_titles;
+ $this->html_hashes = array();
+ $this->in_anchor = false;
+ $this->in_emphasis_processing = false;
+ }
+
+ /**
+ * Called after the transformation process to clear any variable which may
+ * be taking up memory unnecessarly.
+ * @return void
+ */
+ protected function teardown() {
+ $this->urls = array();
+ $this->titles = array();
+ $this->html_hashes = array();
+ }
+
+ /**
+ * Main function. Performs some preprocessing on the input text and pass
+ * it through the document gamut.
+ *
+ * @api
+ *
+ * @param string $text
+ * @return string
+ */
+ public function transform($text) {
+ $this->setup();
+
+ # Remove UTF-8 BOM and marker character in input, if present.
+ $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
+
+ # Standardize line endings:
+ # DOS to Unix and Mac to Unix
+ $text = preg_replace('{\r\n?}', "\n", $text);
+
+ # Make sure $text ends with a couple of newlines:
+ $text .= "\n\n";
+
+ # Convert all tabs to spaces.
+ $text = $this->detab($text);
+
+ # Turn block-level HTML blocks into hash entries
+ $text = $this->hashHTMLBlocks($text);
+
+ # Strip any lines consisting only of spaces and tabs.
+ # This makes subsequent regexen easier to write, because we can
+ # match consecutive blank lines with /\n+/ instead of something
+ # contorted like /[ ]*\n+/ .
+ $text = preg_replace('/^[ ]+$/m', '', $text);
+
+ # Run document gamut methods.
+ foreach ($this->document_gamut as $method => $priority) {
+ $text = $this->$method($text);
+ }
+
+ $this->teardown();
+
+ return $text . "\n";
+ }
+
+ /**
+ * Define the document gamut
+ * @var array
+ */
+ protected $document_gamut = array(
+ // Strip link definitions, store in hashes.
+ "stripLinkDefinitions" => 20,
+ "runBasicBlockGamut" => 30,
+ );
+
+ /**
+ * Strips link definitions from text, stores the URLs and titles in
+ * hash references
+ * @param string $text
+ * @return string
+ */
+ protected function stripLinkDefinitions($text) {
+
+ $less_than_tab = $this->tab_width - 1;
+
+ // Link defs are in the form: ^[id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ [ ]*
+ (?:
+ <(.+?)> # url = $2
+ |
+ (\S+?) # url = $3
+ )
+ [ ]*
+ \n? # maybe one newline
+ [ ]*
+ (?:
+ (?<=\s) # lookbehind for whitespace
+ ["(]
+ (.*?) # title = $4
+ [")]
+ [ ]*
+ )? # title is optional
+ (?:\n+|\Z)
+ }xm',
+ array($this, '_stripLinkDefinitions_callback'),
+ $text
+ );
+ return $text;
+ }
+
+ /**
+ * The callback to strip link definitions
+ * @param array $matches
+ * @return string
+ */
+ protected function _stripLinkDefinitions_callback($matches) {
+ $link_id = strtolower($matches[1]);
+ $url = $matches[2] == '' ? $matches[3] : $matches[2];
+ $this->urls[$link_id] = $url;
+ $this->titles[$link_id] =& $matches[4];
+ return ''; // String that will replace the block
+ }
+
+ /**
+ * Hashify HTML blocks
+ * @param string $text
+ * @return string
+ */
+ protected function hashHTMLBlocks($text) {
+ if ($this->no_markup) {
+ return $text;
+ }
+
+ $less_than_tab = $this->tab_width - 1;
+
+ /**
+ * Hashify HTML blocks:
+ *
+ * We only want to do this for block-level HTML tags, such as headers,
+ * lists, and tables. That's because we still want to wrap <p>s around
+ * "paragraphs" that are wrapped in non-block-level tags, such as
+ * anchors, phrase emphasis, and spans. The list of tags we're looking
+ * for is hard-coded:
+ *
+ * * List "a" is made of tags which can be both inline or block-level.
+ * These will be treated block-level when the start tag is alone on
+ * its line, otherwise they're not matched here and will be taken as
+ * inline later.
+ * * List "b" is made of tags which are always block-level;
+ */
+ $block_tags_a_re = 'ins|del';
+ $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
+ 'script|noscript|style|form|fieldset|iframe|math|svg|'.
+ 'article|section|nav|aside|hgroup|header|footer|'.
+ 'figure';
+
+ // Regular expression for the content of a block tag.
+ $nested_tags_level = 4;
+ $attr = '
+ (?> # optional tag attributes
+ \s # starts with whitespace
+ (?>
+ [^>"/]+ # text outside quotes
+ |
+ /+(?!>) # slash not followed by ">"
+ |
+ "[^"]*" # text inside double quotes (tolerate ">")
+ |
+ \'[^\']*\' # text inside single quotes (tolerate ">")
+ )*
+ )?
+ ';
+ $content =
+ str_repeat('
+ (?>
+ [^<]+ # content without tag
+ |
+ <\2 # nested opening tag
+ '.$attr.' # attributes
+ (?>
+ />
+ |
+ >', $nested_tags_level). // end of opening tag
+ '.*?'. // last level nested tag content
+ str_repeat('
+ </\2\s*> # closing nested tag
+ )
+ |
+ <(?!/\2\s*> # other tags with a different name
+ )
+ )*',
+ $nested_tags_level);
+ $content2 = str_replace('\2', '\3', $content);
+
+ /**
+ * First, look for nested blocks, e.g.:
+ * <div>
+ * <div>
+ * tags for inner block must be indented.
+ * </div>
+ * </div>
+ *
+ * The outermost tags must start at the left margin for this to match,
+ * and the inner nested divs must be indented.
+ * We need to do this before the next, more liberal match, because the
+ * next match will start at the first `<div>` and stop at the
+ * first `</div>`.
+ */
+ $text = preg_replace_callback('{(?>
+ (?>
+ (?<=\n) # Starting on its own line
+ | # or
+ \A\n? # the at beginning of the doc
+ )
+ ( # save in $1
+
+ # Match from `\n<tag>` to `</tag>\n`, handling nested tags
+ # in between.
+
+ [ ]{0,'.$less_than_tab.'}
+ <('.$block_tags_b_re.')# start tag = $2
+ '.$attr.'> # attributes followed by > and \n
+ '.$content.' # content, support nesting
+ </\2> # the matching end tag
+ [ ]* # trailing spaces/tabs
+ (?=\n+|\Z) # followed by a newline or end of document
+
+ | # Special version for tags of group a.
+
+ [ ]{0,'.$less_than_tab.'}
+ <('.$block_tags_a_re.')# start tag = $3
+ '.$attr.'>[ ]*\n # attributes followed by >
+ '.$content2.' # content, support nesting
+ </\3> # the matching end tag
+ [ ]* # trailing spaces/tabs
+ (?=\n+|\Z) # followed by a newline or end of document
+
+ | # Special case just for <hr />. It was easier to make a special
+ # case than to make the other regex more complicated.
+
+ [ ]{0,'.$less_than_tab.'}
+ <(hr) # start tag = $2
+ '.$attr.' # attributes
+ /?> # the matching end tag
+ [ ]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+
+ | # Special case for standalone HTML comments:
+
+ [ ]{0,'.$less_than_tab.'}
+ (?s:
+ <!-- .*? -->
+ )
+ [ ]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+
+ | # PHP and ASP-style processor instructions (<? and <%)
+
+ [ ]{0,'.$less_than_tab.'}
+ (?s:
+ <([?%]) # $2
+ .*?
+ \2>
+ )
+ [ ]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+
+ )
+ )}Sxmi',
+ array($this, '_hashHTMLBlocks_callback'),
+ $text
+ );
+
+ return $text;
+ }
+
+ /**
+ * The callback for hashing HTML blocks
+ * @param string $matches
+ * @return string
+ */
+ protected function _hashHTMLBlocks_callback($matches) {
+ $text = $matches[1];
+ $key = $this->hashBlock($text);
+ return "\n\n$key\n\n";
+ }
+
+ /**
+ * Called whenever a tag must be hashed when a function insert an atomic
+ * element in the text stream. Passing $text to through this function gives
+ * a unique text-token which will be reverted back when calling unhash.
+ *
+ * The $boundary argument specify what character should be used to surround
+ * the token. By convension, "B" is used for block elements that needs not
+ * to be wrapped into paragraph tags at the end, ":" is used for elements
+ * that are word separators and "X" is used in the general case.
+ *
+ * @param string $text
+ * @param string $boundary
+ * @return string
+ */
+ protected function hashPart($text, $boundary = 'X') {
+ // Swap back any tag hash found in $text so we do not have to `unhash`
+ // multiple times at the end.
+ $text = $this->unhash($text);
+
+ // Then hash the block.
+ static $i = 0;
+ $key = "$boundary\x1A" . ++$i . $boundary;
+ $this->html_hashes[$key] = $text;
+ return $key; // String that will replace the tag.
+ }
+
+ /**
+ * Shortcut function for hashPart with block-level boundaries.
+ * @param string $text
+ * @return string
+ */
+ protected function hashBlock($text) {
+ return $this->hashPart($text, 'B');
+ }
+
+ /**
+ * Define the block gamut - these are all the transformations that form
+ * block-level tags like paragraphs, headers, and list items.
+ * @var array
+ */
+ protected $block_gamut = array(
+ "doHeaders" => 10,
+ "doHorizontalRules" => 20,
+ "doLists" => 40,
+ "doCodeBlocks" => 50,
+ "doBlockQuotes" => 60,
+ );
+
+ /**
+ * Run block gamut tranformations.
+ *
+ * We need to escape raw HTML in Markdown source before doing anything
+ * else. This need to be done for each block, and not only at the
+ * begining in the Markdown function since hashed blocks can be part of
+ * list items and could have been indented. Indented blocks would have
+ * been seen as a code block in a previous pass of hashHTMLBlocks.
+ *
+ * @param string $text
+ * @return string
+ */
+ protected function runBlockGamut($text) {
+ $text = $this->hashHTMLBlocks($text);
+ return $this->runBasicBlockGamut($text);
+ }
+
+ /**
+ * Run block gamut tranformations, without hashing HTML blocks. This is
+ * useful when HTML blocks are known to be already hashed, like in the first
+ * whole-document pass.
+ *
+ * @param string $text
+ * @return string
+ */
+ protected function runBasicBlockGamut($text) {
+
+ foreach ($this->block_gamut as $method => $priority) {
+ $text = $this->$method($text);
+ }
+
+ // Finally form paragraph and restore hashed blocks.
+ $text = $this->formParagraphs($text);
+
+ return $text;
+ }
+
+ /**
+ * Convert horizontal rules
+ * @param string $text
+ * @return string
+ */
+ protected function doHorizontalRules($text) {
+ return preg_replace(
+ '{
+ ^[ ]{0,3} # Leading space
+ ([-*_]) # $1: First marker
+ (?> # Repeated marker group
+ [ ]{0,2} # Zero, one, or two spaces.
+ \1 # Marker character
+ ){2,} # Group repeated at least twice
+ [ ]* # Tailing spaces
+ $ # End of line.
+ }mx',
+ "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
+ $text
+ );
+ }
+
+ /**
+ * These are all the transformations that occur *within* block-level
+ * tags like paragraphs, headers, and list items.
+ * @var array
+ */
+ protected $span_gamut = array(
+ // Process character escapes, code spans, and inline HTML
+ // in one shot.
+ "parseSpan" => -30,
+ // Process anchor and image tags. Images must come first,
+ // because ![foo][f] looks like an anchor.
+ "doImages" => 10,
+ "doAnchors" => 20,
+ // Make links out of things like `<https://example.com/>`
+ // Must come after doAnchors, because you can use < and >
+ // delimiters in inline links like [this](<url>).
+ "doAutoLinks" => 30,
+ "encodeAmpsAndAngles" => 40,
+ "doItalicsAndBold" => 50,
+ "doHardBreaks" => 60,
+ );
+
+ /**
+ * Run span gamut transformations
+ * @param string $text
+ * @return string
+ */
+ protected function runSpanGamut($text) {
+ foreach ($this->span_gamut as $method => $priority) {
+ $text = $this->$method($text);
+ }
+
+ return $text;
+ }
+
+ /**
+ * Do hard breaks
+ * @param string $text
+ * @return string
+ */
+ protected function doHardBreaks($text) {
+ if ($this->hard_wrap) {
+ return preg_replace_callback('/ *\n/',
+ array($this, '_doHardBreaks_callback'), $text);
+ } else {
+ return preg_replace_callback('/ {2,}\n/',
+ array($this, '_doHardBreaks_callback'), $text);
+ }
+ }
+
+ /**
+ * Trigger part hashing for the hard break (callback method)
+ * @param array $matches
+ * @return string
+ */
+ protected function _doHardBreaks_callback($matches) {
+ return $this->hashPart("<br$this->empty_element_suffix\n");
+ }
+
+ /**
+ * Turn Markdown link shortcuts into XHTML <a> tags.
+ * @param string $text
+ * @return string
+ */
+ protected function doAnchors($text) {
+ if ($this->in_anchor) {
+ return $text;
+ }
+ $this->in_anchor = true;
+
+ // First, handle reference-style links: [link text] [id]
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ('.$this->nested_brackets_re.') # link text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+ )
+ }xs',
+ array($this, '_doAnchors_reference_callback'), $text);
+
+ // Next, inline-style links: [link text](url "optional title")
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ('.$this->nested_brackets_re.') # link text = $2
+ \]
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(.+?)> # href = $3
+ |
+ ('.$this->nested_url_parenthesis_re.') # href = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # Title = $7
+ \6 # matching quote
+ [ \n]* # ignore any spaces/tabs between closing quote and )
+ )? # title is optional
+ \)
+ )
+ }xs',
+ array($this, '_doAnchors_inline_callback'), $text);
+
+ // Last, handle reference-style shortcuts: [link text]
+ // These must come last in case you've also got [link text][1]
+ // or [link text](/foo)
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ([^\[\]]+) # link text = $2; can\'t contain [ or ]
+ \]
+ )
+ }xs',
+ array($this, '_doAnchors_reference_callback'), $text);
+
+ $this->in_anchor = false;
+ return $text;
+ }
+
+ /**
+ * Callback method to parse referenced anchors
+ * @param string $matches
+ * @return string
+ */
+ protected function _doAnchors_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $matches[2];
+ $link_id =& $matches[3];
+
+ if ($link_id == "") {
+ // for shortcut links like [this][] or [this].
+ $link_id = $link_text;
+ }
+
+ // lower-case and turn embedded newlines into spaces
+ $link_id = strtolower($link_id);
+ $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+ if (isset($this->urls[$link_id])) {
+ $url = $this->urls[$link_id];
+ $url = $this->encodeURLAttribute($url);
+
+ $result = "<a href=\"$url\"";
+ if ( isset( $this->titles[$link_id] ) ) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text</a>";
+ $result = $this->hashPart($result);
+ } else {
+ $result = $whole_match;
+ }
+ return $result;
+ }
+
+ /**
+ * Callback method to parse inline anchors
+ * @param string $matches
+ * @return string
+ */
+ protected function _doAnchors_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $this->runSpanGamut($matches[2]);
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+
+ // If the URL was of the form <s p a c e s> it got caught by the HTML
+ // tag parser and hashed. Need to reverse the process before using
+ // the URL.
+ $unhashed = $this->unhash($url);
+ if ($unhashed != $url)
+ $url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
+
+ $url = $this->encodeURLAttribute($url);
+
+ $result = "<a href=\"$url\"";
+ if (isset($title)) {
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text</a>";
+
+ return $this->hashPart($result);
+ }
+
+ /**
+ * Turn Markdown image shortcuts into <img> tags.
+ * @param string $text
+ * @return string
+ */
+ protected function doImages($text) {
+ // First, handle reference-style labeled images: ![alt text][id]
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ ('.$this->nested_brackets_re.') # alt text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+
+ )
+ }xs',
+ array($this, '_doImages_reference_callback'), $text);
+
+ // Next, handle inline images: 
+ // Don't forget: encode * and _
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ ('.$this->nested_brackets_re.') # alt text = $2
+ \]
+ \s? # One optional whitespace character
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(\S*)> # src url = $3
+ |
+ ('.$this->nested_url_parenthesis_re.') # src url = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # title = $7
+ \6 # matching quote
+ [ \n]*
+ )? # title is optional
+ \)
+ )
+ }xs',
+ array($this, '_doImages_inline_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Callback to parse references image tags
+ * @param array $matches
+ * @return string
+ */
+ protected function _doImages_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $link_id = strtolower($matches[3]);
+
+ if ($link_id == "") {
+ $link_id = strtolower($alt_text); // for shortcut links like ![this][].
+ }
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ if (isset($this->urls[$link_id])) {
+ $url = $this->encodeURLAttribute($this->urls[$link_id]);
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
+ if (isset($this->titles[$link_id])) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ $result .= $this->empty_element_suffix;
+ $result = $this->hashPart($result);
+ } else {
+ // If there's no such link ID, leave intact:
+ $result = $whole_match;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Callback to parse inline image tags
+ * @param array $matches
+ * @return string
+ */
+ protected function _doImages_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ $url = $this->encodeURLAttribute($url);
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
+ if (isset($title)) {
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\""; // $title already quoted
+ }
+ $result .= $this->empty_element_suffix;
+
+ return $this->hashPart($result);
+ }
+
+ /**
+ * Parse Markdown heading elements to HTML
+ * @param string $text
+ * @return string
+ */
+ protected function doHeaders($text) {
+ /**
+ * Setext-style headers:
+ * Header 1
+ * ========
+ *
+ * Header 2
+ * --------
+ */
+ $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
+ array($this, '_doHeaders_callback_setext'), $text);
+
+ /**
+ * atx-style headers:
+ * # Header 1
+ * ## Header 2
+ * ## Header 2 with closing hashes ##
+ * ...
+ * ###### Header 6
+ */
+ $text = preg_replace_callback('{
+ ^(\#{1,6}) # $1 = string of #\'s
+ [ ]*
+ (.+?) # $2 = Header text
+ [ ]*
+ \#* # optional closing #\'s (not counted)
+ \n+
+ }xm',
+ array($this, '_doHeaders_callback_atx'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Setext header parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doHeaders_callback_setext($matches) {
+ // Terrible hack to check we haven't found an empty list item.
+ if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) {
+ return $matches[0];
+ }
+
+ $level = $matches[2]{0} == '=' ? 1 : 2;
+
+ // ID attribute generation
+ $idAtt = $this->_generateIdFromHeaderValue($matches[1]);
+
+ $block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+ /**
+ * ATX header parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doHeaders_callback_atx($matches) {
+ // ID attribute generation
+ $idAtt = $this->_generateIdFromHeaderValue($matches[2]);
+
+ $level = strlen($matches[1]);
+ $block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+ /**
+ * If a header_id_func property is set, we can use it to automatically
+ * generate an id attribute.
+ *
+ * This method returns a string in the form id="foo", or an empty string
+ * otherwise.
+ * @param string $headerValue
+ * @return string
+ */
+ protected function _generateIdFromHeaderValue($headerValue) {
+ if (!is_callable($this->header_id_func)) {
+ return "";
+ }
+
+ $idValue = call_user_func($this->header_id_func, $headerValue);
+ if (!$idValue) {
+ return "";
+ }
+
+ return ' id="' . $this->encodeAttribute($idValue) . '"';
+ }
+
+ /**
+ * Form HTML ordered (numbered) and unordered (bulleted) lists.
+ * @param string $text
+ * @return string
+ */
+ protected function doLists($text) {
+ $less_than_tab = $this->tab_width - 1;
+
+ // Re-usable patterns to match list item bullets and number markers:
+ $marker_ul_re = '[*+-]';
+ $marker_ol_re = '\d+[\.]';
+
+ $markers_relist = array(
+ $marker_ul_re => $marker_ol_re,
+ $marker_ol_re => $marker_ul_re,
+ );
+
+ foreach ($markers_relist as $marker_re => $other_marker_re) {
+ // Re-usable pattern to match any entirel ul or ol list:
+ $whole_list_re = '
+ ( # $1 = whole list
+ ( # $2
+ ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces
+ ('.$marker_re.') # $4 = first list item marker
+ [ ]+
+ )
+ (?s:.+?)
+ ( # $5
+ \z
+ |
+ \n{2,}
+ (?=\S)
+ (?! # Negative lookahead for another list item marker
+ [ ]*
+ '.$marker_re.'[ ]+
+ )
+ |
+ (?= # Lookahead for another kind of list
+ \n
+ \3 # Must have the same indentation
+ '.$other_marker_re.'[ ]+
+ )
+ )
+ )
+ '; // mx
+
+ // We use a different prefix before nested lists than top-level lists.
+ //See extended comment in _ProcessListItems().
+
+ if ($this->list_level) {
+ $text = preg_replace_callback('{
+ ^
+ '.$whole_list_re.'
+ }mx',
+ array($this, '_doLists_callback'), $text);
+ } else {
+ $text = preg_replace_callback('{
+ (?:(?<=\n)\n|\A\n?) # Must eat the newline
+ '.$whole_list_re.'
+ }mx',
+ array($this, '_doLists_callback'), $text);
+ }
+ }
+
+ return $text;
+ }
+
+ /**
+ * List parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doLists_callback($matches) {
+ // Re-usable patterns to match list item bullets and number markers:
+ $marker_ul_re = '[*+-]';
+ $marker_ol_re = '\d+[\.]';
+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+ $marker_ol_start_re = '[0-9]+';
+
+ $list = $matches[1];
+ $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
+
+ $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
+
+ $list .= "\n";
+ $result = $this->processListItems($list, $marker_any_re);
+
+ $ol_start = 1;
+ if ($this->enhanced_ordered_list) {
+ // Get the start number for ordered list.
+ if ($list_type == 'ol') {
+ $ol_start_array = array();
+ $ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
+ if ($ol_start_check){
+ $ol_start = $ol_start_array[0];
+ }
+ }
+ }
+
+ if ($ol_start > 1 && $list_type == 'ol'){
+ $result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
+ } else {
+ $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
+ }
+ return "\n". $result ."\n\n";
+ }
+
+ /**
+ * Nesting tracker for list levels
+ * @var integer
+ */
+ protected $list_level = 0;
+
+ /**
+ * Process the contents of a single ordered or unordered list, splitting it
+ * into individual list items.
+ * @param string $list_str
+ * @param string $marker_any_re
+ * @return string
+ */
+ protected function processListItems($list_str, $marker_any_re) {
+ /**
+ * The $this->list_level global keeps track of when we're inside a list.
+ * Each time we enter a list, we increment it; when we leave a list,
+ * we decrement. If it's zero, we're not in a list anymore.
+ *
+ * We do this because when we're not inside a list, we want to treat
+ * something like this:
+ *
+ * I recommend upgrading to version
+ * 8. Oops, now this line is treated
+ * as a sub-list.
+ *
+ * As a single paragraph, despite the fact that the second line starts
+ * with a digit-period-space sequence.
+ *
+ * Whereas when we're inside a list (or sub-list), that line will be
+ * treated as the start of a sub-list. What a kludge, huh? This is
+ * an aspect of Markdown's syntax that's hard to parse perfectly
+ * without resorting to mind-reading. Perhaps the solution is to
+ * change the syntax rules such that sub-lists must start with a
+ * starting cardinal number; e.g. "1." or "a.".
+ */
+ $this->list_level++;
+
+ // Trim trailing blank lines:
+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+ $list_str = preg_replace_callback('{
+ (\n)? # leading line = $1
+ (^[ ]*) # leading whitespace = $2
+ ('.$marker_any_re.' # list marker and space = $3
+ (?:[ ]+|(?=\n)) # space only required if item is not empty
+ )
+ ((?s:.*?)) # list item text = $4
+ (?:(\n+(?=\n))|\n) # tailing blank line = $5
+ (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
+ }xm',
+ array($this, '_processListItems_callback'), $list_str);
+
+ $this->list_level--;
+ return $list_str;
+ }
+
+ /**
+ * List item parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _processListItems_callback($matches) {
+ $item = $matches[4];
+ $leading_line =& $matches[1];
+ $leading_space =& $matches[2];
+ $marker_space = $matches[3];
+ $tailing_blank_line =& $matches[5];
+
+ if ($leading_line || $tailing_blank_line ||
+ preg_match('/\n{2,}/', $item))
+ {
+ // Replace marker with the appropriate whitespace indentation
+ $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
+ $item = $this->runBlockGamut($this->outdent($item)."\n");
+ } else {
+ // Recursion for sub-lists:
+ $item = $this->doLists($this->outdent($item));
+ $item = $this->formParagraphs($item, false);
+ }
+
+ return "<li>" . $item . "</li>\n";
+ }
+
+ /**
+ * Process Markdown `<pre><code>` blocks.
+ * @param string $text
+ * @return string
+ */
+ protected function doCodeBlocks($text) {
+ $text = preg_replace_callback('{
+ (?:\n\n|\A\n?)
+ ( # $1 = the code block -- one or more lines, starting with a space/tab
+ (?>
+ [ ]{'.$this->tab_width.'} # Lines must start with a tab or a tab-width of spaces
+ .*\n+
+ )+
+ )
+ ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
+ }xm',
+ array($this, '_doCodeBlocks_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Code block parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doCodeBlocks_callback($matches) {
+ $codeblock = $matches[1];
+
+ $codeblock = $this->outdent($codeblock);
+ if ($this->code_block_content_func) {
+ $codeblock = call_user_func($this->code_block_content_func, $codeblock, "");
+ } else {
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+ }
+
+ # trim leading newlines and trailing newlines
+ $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+
+ $codeblock = "<pre><code>$codeblock\n</code></pre>";
+ return "\n\n" . $this->hashBlock($codeblock) . "\n\n";
+ }
+
+ /**
+ * Create a code span markup for $code. Called from handleSpanToken.
+ * @param string $code
+ * @return string
+ */
+ protected function makeCodeSpan($code) {
+ if ($this->code_span_content_func) {
+ $code = call_user_func($this->code_span_content_func, $code);
+ } else {
+ $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+ }
+ return $this->hashPart("<code>$code</code>");
+ }
+
+ /**
+ * Define the emphasis operators with their regex matches
+ * @var array
+ */
+ protected $em_relist = array(
+ '' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)',
+ '*' => '(?<![\s*])\*(?!\*)',
+ '_' => '(?<![\s_])_(?!_)',
+ );
+
+ /**
+ * Define the strong operators with their regex matches
+ * @var array
+ */
+ protected $strong_relist = array(
+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)',
+ '**' => '(?<![\s*])\*\*(?!\*)',
+ '__' => '(?<![\s_])__(?!_)',
+ );
+
+ /**
+ * Define the emphasis + strong operators with their regex matches
+ * @var array
+ */
+ protected $em_strong_relist = array(
+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)',
+ '***' => '(?<![\s*])\*\*\*(?!\*)',
+ '___' => '(?<![\s_])___(?!_)',
+ );
+
+ /**
+ * Container for prepared regular expressions
+ * @var array
+ */
+ protected $em_strong_prepared_relist;
+
+ /**
+ * Prepare regular expressions for searching emphasis tokens in any
+ * context.
+ * @return void
+ */
+ protected function prepareItalicsAndBold() {
+ foreach ($this->em_relist as $em => $em_re) {
+ foreach ($this->strong_relist as $strong => $strong_re) {
+ // Construct list of allowed token expressions.
+ $token_relist = array();
+ if (isset($this->em_strong_relist["$em$strong"])) {
+ $token_relist[] = $this->em_strong_relist["$em$strong"];
+ }
+ $token_relist[] = $em_re;
+ $token_relist[] = $strong_re;
+
+ // Construct master expression from list.
+ $token_re = '{(' . implode('|', $token_relist) . ')}';
+ $this->em_strong_prepared_relist["$em$strong"] = $token_re;
+ }
+ }
+ }
+
+ /**
+ * Convert Markdown italics (emphasis) and bold (strong) to HTML
+ * @param string $text
+ * @return string
+ */
+ protected function doItalicsAndBold($text) {
+ if ($this->in_emphasis_processing) {
+ return $text; // avoid reentrency
+ }
+ $this->in_emphasis_processing = true;
+
+ $token_stack = array('');
+ $text_stack = array('');
+ $em = '';
+ $strong = '';
+ $tree_char_em = false;
+
+ while (1) {
+ // Get prepared regular expression for seraching emphasis tokens
+ // in current context.
+ $token_re = $this->em_strong_prepared_relist["$em$strong"];
+
+ // Each loop iteration search for the next emphasis token.
+ // Each token is then passed to handleSpanToken.
+ $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+ $text_stack[0] .= $parts[0];
+ $token =& $parts[1];
+ $text =& $parts[2];
+
+ if (empty($token)) {
+ // Reached end of text span: empty stack without emitting.
+ // any more emphasis.
+ while ($token_stack[0]) {
+ $text_stack[1] .= array_shift($token_stack);
+ $text_stack[0] .= array_shift($text_stack);
+ }
+ break;
+ }
+
+ $token_len = strlen($token);
+ if ($tree_char_em) {
+ // Reached closing marker while inside a three-char emphasis.
+ if ($token_len == 3) {
+ // Three-char closing marker, close em and strong.
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<strong><em>$span</em></strong>";
+ $text_stack[0] .= $this->hashPart($span);
+ $em = '';
+ $strong = '';
+ } else {
+ // Other closing marker: close one em or strong and
+ // change current token state to match the other
+ $token_stack[0] = str_repeat($token{0}, 3-$token_len);
+ $tag = $token_len == 2 ? "strong" : "em";
+ $span = $text_stack[0];
+ $span = $this->runSpanGamut($span);
+ $span = "<$tag>$span</$tag>";
+ $text_stack[0] = $this->hashPart($span);
+ $$tag = ''; // $$tag stands for $em or $strong
+ }
+ $tree_char_em = false;
+ } else if ($token_len == 3) {
+ if ($em) {
+ // Reached closing marker for both em and strong.
+ // Closing strong marker:
+ for ($i = 0; $i < 2; ++$i) {
+ $shifted_token = array_shift($token_stack);
+ $tag = strlen($shifted_token) == 2 ? "strong" : "em";
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<$tag>$span</$tag>";
+ $text_stack[0] .= $this->hashPart($span);
+ $$tag = ''; // $$tag stands for $em or $strong
+ }
+ } else {
+ // Reached opening three-char emphasis marker. Push on token
+ // stack; will be handled by the special condition above.
+ $em = $token{0};
+ $strong = "$em$em";
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $tree_char_em = true;
+ }
+ } else if ($token_len == 2) {
+ if ($strong) {
+ // Unwind any dangling emphasis marker:
+ if (strlen($token_stack[0]) == 1) {
+ $text_stack[1] .= array_shift($token_stack);
+ $text_stack[0] .= array_shift($text_stack);
+ $em = '';
+ }
+ // Closing strong marker:
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<strong>$span</strong>";
+ $text_stack[0] .= $this->hashPart($span);
+ $strong = '';
+ } else {
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $strong = $token;
+ }
+ } else {
+ // Here $token_len == 1
+ if ($em) {
+ if (strlen($token_stack[0]) == 1) {
+ // Closing emphasis marker:
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<em>$span</em>";
+ $text_stack[0] .= $this->hashPart($span);
+ $em = '';
+ } else {
+ $text_stack[0] .= $token;
+ }
+ } else {
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $em = $token;
+ }
+ }
+ }
+ $this->in_emphasis_processing = false;
+ return $text_stack[0];
+ }
+
+ /**
+ * Parse Markdown blockquotes to HTML
+ * @param string $text
+ * @return string
+ */
+ protected function doBlockQuotes($text) {
+ $text = preg_replace_callback('/
+ ( # Wrap whole match in $1
+ (?>
+ ^[ ]*>[ ]? # ">" at the start of a line
+ .+\n # rest of the first line
+ (.+\n)* # subsequent consecutive lines
+ \n* # blanks
+ )+
+ )
+ /xm',
+ array($this, '_doBlockQuotes_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Blockquote parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doBlockQuotes_callback($matches) {
+ $bq = $matches[1];
+ // trim one level of quoting - trim whitespace-only lines
+ $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+ $bq = $this->runBlockGamut($bq); // recurse
+
+ $bq = preg_replace('/^/m', " ", $bq);
+ // These leading spaces cause problem with <pre> content,
+ // so we need to fix that:
+ $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
+ array($this, '_doBlockQuotes_callback2'), $bq);
+
+ return "\n" . $this->hashBlock("<blockquote>\n$bq\n</blockquote>") . "\n\n";
+ }
+
+ /**
+ * Blockquote parsing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doBlockQuotes_callback2($matches) {
+ $pre = $matches[1];
+ $pre = preg_replace('/^ /m', '', $pre);
+ return $pre;
+ }
+
+ /**
+ * Parse paragraphs
+ *
+ * @param string $text String to process in paragraphs
+ * @param boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
+ * @return string
+ */
+ protected function formParagraphs($text, $wrap_in_p = true) {
+ // Strip leading and trailing lines:
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+ // Wrap <p> tags and unhashify HTML blocks
+ foreach ($grafs as $key => $value) {
+ if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+ // Is a paragraph.
+ $value = $this->runSpanGamut($value);
+ if ($wrap_in_p) {
+ $value = preg_replace('/^([ ]*)/', "<p>", $value);
+ $value .= "</p>";
+ }
+ $grafs[$key] = $this->unhash($value);
+ } else {
+ // Is a block.
+ // Modify elements of @grafs in-place...
+ $graf = $value;
+ $block = $this->html_hashes[$graf];
+ $graf = $block;
+// if (preg_match('{
+// \A
+// ( # $1 = <div> tag
+// <div \s+
+// [^>]*
+// \b
+// markdown\s*=\s* ([\'"]) # $2 = attr quote char
+// 1
+// \2
+// [^>]*
+// >
+// )
+// ( # $3 = contents
+// .*
+// )
+// (</div>) # $4 = closing tag
+// \z
+// }xs', $block, $matches))
+// {
+// list(, $div_open, , $div_content, $div_close) = $matches;
+//
+// // We can't call Markdown(), because that resets the hash;
+// // that initialization code should be pulled into its own sub, though.
+// $div_content = $this->hashHTMLBlocks($div_content);
+//
+// // Run document gamut methods on the content.
+// foreach ($this->document_gamut as $method => $priority) {
+// $div_content = $this->$method($div_content);
+// }
+//
+// $div_open = preg_replace(
+// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+//
+// $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+// }
+ $grafs[$key] = $graf;
+ }
+ }
+
+ return implode("\n\n", $grafs);
+ }
+
+ /**
+ * Encode text for a double-quoted HTML attribute. This function
+ * is *not* suitable for attributes enclosed in single quotes.
+ * @param string $text
+ * @return string
+ */
+ protected function encodeAttribute($text) {
+ $text = $this->encodeAmpsAndAngles($text);
+ $text = str_replace('"', '"', $text);
+ return $text;
+ }
+
+ /**
+ * Encode text for a double-quoted HTML attribute containing a URL,
+ * applying the URL filter if set. Also generates the textual
+ * representation for the URL (removing mailto: or tel:) storing it in $text.
+ * This function is *not* suitable for attributes enclosed in single quotes.
+ *
+ * @param string $url
+ * @param string &$text Passed by reference
+ * @return string URL
+ */
+ protected function encodeURLAttribute($url, &$text = null) {
+ if ($this->url_filter_func) {
+ $url = call_user_func($this->url_filter_func, $url);
+ }
+
+ if (preg_match('{^mailto:}i', $url)) {
+ $url = $this->encodeEntityObfuscatedAttribute($url, $text, 7);
+ } else if (preg_match('{^tel:}i', $url)) {
+ $url = $this->encodeAttribute($url);
+ $text = substr($url, 4);
+ } else {
+ $url = $this->encodeAttribute($url);
+ $text = $url;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Smart processing for ampersands and angle brackets that need to
+ * be encoded. Valid character entities are left alone unless the
+ * no-entities mode is set.
+ * @param string $text
+ * @return string
+ */
+ protected function encodeAmpsAndAngles($text) {
+ if ($this->no_entities) {
+ $text = str_replace('&', '&', $text);
+ } else {
+ // Ampersand-encoding based entirely on Nat Irons's Amputator
+ // MT plugin: <http://bumppo.net/projects/amputator/>
+ $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
+ '&', $text);
+ }
+ // Encode remaining <'s
+ $text = str_replace('<', '<', $text);
+
+ return $text;
+ }
+
+ /**
+ * Parse Markdown automatic links to anchor HTML tags
+ * @param string $text
+ * @return string
+ */
+ protected function doAutoLinks($text) {
+ $text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i',
+ array($this, '_doAutoLinks_url_callback'), $text);
+
+ // Email addresses: <address@domain.foo>
+ $text = preg_replace_callback('{
+ <
+ (?:mailto:)?
+ (
+ (?:
+ [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
+ |
+ ".*?"
+ )
+ \@
+ (?:
+ [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+ |
+ \[[\d.a-fA-F:]+\] # IPv4 & IPv6
+ )
+ )
+ >
+ }xi',
+ array($this, '_doAutoLinks_email_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Parse URL callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doAutoLinks_url_callback($matches) {
+ $url = $this->encodeURLAttribute($matches[1], $text);
+ $link = "<a href=\"$url\">$text</a>";
+ return $this->hashPart($link);
+ }
+
+ /**
+ * Parse email address callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _doAutoLinks_email_callback($matches) {
+ $addr = $matches[1];
+ $url = $this->encodeURLAttribute("mailto:$addr", $text);
+ $link = "<a href=\"$url\">$text</a>";
+ return $this->hashPart($link);
+ }
+
+ /**
+ * Input: some text to obfuscate, e.g. "mailto:foo@example.com"
+ *
+ * Output: the same text but with most characters encoded as either a
+ * decimal or hex entity, in the hopes of foiling most address
+ * harvesting spam bots. E.g.:
+ *
+ * mailto:foo
+ * @example.co
+ * m
+ *
+ * Note: the additional output $tail is assigned the same value as the
+ * ouput, minus the number of characters specified by $head_length.
+ *
+ * Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+ * With some optimizations by Milian Wolff. Forced encoding of HTML
+ * attribute special characters by Allan Odgaard.
+ *
+ * @param string $text
+ * @param string &$tail
+ * @param integer $head_length
+ * @return string
+ */
+ protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) {
+ if ($text == "") {
+ return $tail = "";
+ }
+
+ $chars = preg_split('/(?<!^)(?!$)/', $text);
+ $seed = (int)abs(crc32($text) / strlen($text)); // Deterministic seed.
+
+ foreach ($chars as $key => $char) {
+ $ord = ord($char);
+ // Ignore non-ascii chars.
+ if ($ord < 128) {
+ $r = ($seed * (1 + $key)) % 100; // Pseudo-random function.
+ // roughly 10% raw, 45% hex, 45% dec
+ // '@' *must* be encoded. I insist.
+ // '"' and '>' have to be encoded inside the attribute
+ if ($r > 90 && strpos('@"&>', $char) === false) {
+ /* do nothing */
+ } else if ($r < 45) {
+ $chars[$key] = '&#x'.dechex($ord).';';
+ } else {
+ $chars[$key] = '&#'.$ord.';';
+ }
+ }
+ }
+
+ $text = implode('', $chars);
+ $tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text;
+
+ return $text;
+ }
+
+ /**
+ * Take the string $str and parse it into tokens, hashing embeded HTML,
+ * escaped characters and handling code spans.
+ * @param string $str
+ * @return string
+ */
+ protected function parseSpan($str) {
+ $output = '';
+
+ $span_re = '{
+ (
+ \\\\'.$this->escape_chars_re.'
+ |
+ (?<![`\\\\])
+ `+ # code span marker
+ '.( $this->no_markup ? '' : '
+ |
+ <!-- .*? --> # comment
+ |
+ <\?.*?\?> | <%.*?%> # processing instruction
+ |
+ <[!$]?[-a-zA-Z0-9:_]+ # regular tags
+ (?>
+ \s
+ (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+ )?
+ >
+ |
+ <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag
+ |
+ </[-a-zA-Z0-9:_]+\s*> # closing tag
+ ').'
+ )
+ }xs';
+
+ while (1) {
+ // Each loop iteration seach for either the next tag, the next
+ // openning code span marker, or the next escaped character.
+ // Each token is then passed to handleSpanToken.
+ $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ // Create token from text preceding tag.
+ if ($parts[0] != "") {
+ $output .= $parts[0];
+ }
+
+ // Check if we reach the end.
+ if (isset($parts[1])) {
+ $output .= $this->handleSpanToken($parts[1], $parts[2]);
+ $str = $parts[2];
+ } else {
+ break;
+ }
+ }
+
+ return $output;
+ }
+
+ /**
+ * Handle $token provided by parseSpan by determining its nature and
+ * returning the corresponding value that should replace it.
+ * @param string $token
+ * @param string &$str
+ * @return string
+ */
+ protected function handleSpanToken($token, &$str) {
+ switch ($token{0}) {
+ case "\\":
+ return $this->hashPart("&#". ord($token{1}). ";");
+ case "`":
+ // Search for end marker in remaining text.
+ if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
+ $str, $matches))
+ {
+ $str = $matches[2];
+ $codespan = $this->makeCodeSpan($matches[1]);
+ return $this->hashPart($codespan);
+ }
+ return $token; // Return as text since no ending marker found.
+ default:
+ return $this->hashPart($token);
+ }
+ }
+
+ /**
+ * Remove one level of line-leading tabs or spaces
+ * @param string $text
+ * @return string
+ */
+ protected function outdent($text) {
+ return preg_replace('/^(\t|[ ]{1,' . $this->tab_width . '})/m', '', $text);
+ }
+
+
+ /**
+ * String length function for detab. `_initDetab` will create a function to
+ * handle UTF-8 if the default function does not exist.
+ * @var string
+ */
+ protected $utf8_strlen = 'mb_strlen';
+
+ /**
+ * Replace tabs with the appropriate amount of spaces.
+ *
+ * For each line we separate the line in blocks delemited by tab characters.
+ * Then we reconstruct every line by adding the appropriate number of space
+ * between each blocks.
+ *
+ * @param string $text
+ * @return string
+ */
+ protected function detab($text) {
+ $text = preg_replace_callback('/^.*\t.*$/m',
+ array($this, '_detab_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Replace tabs callback
+ * @param string $matches
+ * @return string
+ */
+ protected function _detab_callback($matches) {
+ $line = $matches[0];
+ $strlen = $this->utf8_strlen; // strlen function for UTF-8.
+
+ // Split in blocks.
+ $blocks = explode("\t", $line);
+ // Add each blocks to the line.
+ $line = $blocks[0];
+ unset($blocks[0]); // Do not add first block twice.
+ foreach ($blocks as $block) {
+ // Calculate amount of space, insert spaces, insert block.
+ $amount = $this->tab_width -
+ $strlen($line, 'UTF-8') % $this->tab_width;
+ $line .= str_repeat(" ", $amount) . $block;
+ }
+ return $line;
+ }
+
+ /**
+ * Check for the availability of the function in the `utf8_strlen` property
+ * (initially `mb_strlen`). If the function is not available, create a
+ * function that will loosely count the number of UTF-8 characters with a
+ * regular expression.
+ * @return void
+ */
+ protected function _initDetab() {
+
+ if (function_exists($this->utf8_strlen)) {
+ return;
+ }
+
+ $this->utf8_strlen = function($text) {
+ return preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m);
+ };
+ }
+
+ /**
+ * Swap back in all the tags hashed by _HashHTMLBlocks.
+ * @param string $text
+ * @return string
+ */
+ protected function unhash($text) {
+ return preg_replace_callback('/(.)\x1A[0-9]+\1/',
+ array($this, '_unhash_callback'), $text);
+ }
+
+ /**
+ * Unhashing callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _unhash_callback($matches) {
+ return $this->html_hashes[$matches[0]];
+ }
+}
--- /dev/null
+<?php
+
+// Use this file if you cannot use class autoloading. It will include all the
+// files needed for the MarkdownExtra parser.
+//
+// Take a look at the PSR-0-compatible class autoloading implementation
+// in the Readme.php file if you want a simple autoloader setup.
+
+require_once dirname(__FILE__) . '/MarkdownInterface.php';
+require_once dirname(__FILE__) . '/Markdown.php';
+require_once dirname(__FILE__) . '/MarkdownExtra.php';
--- /dev/null
+<?php
+/**
+ * Markdown Extra - A text-to-HTML conversion tool for web writers
+ *
+ * @package php-markdown
+ * @author Michel Fortin <michel.fortin@michelf.com>
+ * @copyright 2004-2018 Michel Fortin <https://michelf.com/projects/php-markdown/>
+ * @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
+ */
+
+namespace Michelf;
+
+/**
+ * Markdown Extra Parser Class
+ */
+class MarkdownExtra extends \Michelf\Markdown {
+ /**
+ * Configuration variables
+ */
+
+ /**
+ * Prefix for footnote ids.
+ * @var string
+ */
+ public $fn_id_prefix = "";
+
+ /**
+ * Optional title attribute for footnote links and backlinks.
+ * @var string
+ */
+ public $fn_link_title = "";
+ public $fn_backlink_title = "";
+
+ /**
+ * Optional class attribute for footnote links and backlinks.
+ * @var string
+ */
+ public $fn_link_class = "footnote-ref";
+ public $fn_backlink_class = "footnote-backref";
+
+ /**
+ * Content to be displayed within footnote backlinks. The default is '↩';
+ * the U+FE0E on the end is a Unicode variant selector used to prevent iOS
+ * from displaying the arrow character as an emoji.
+ * @var string
+ */
+ public $fn_backlink_html = '↩︎';
+
+ /**
+ * Class name for table cell alignment (%% replaced left/center/right)
+ * For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
+ * If empty, the align attribute is used instead of a class name.
+ * @var string
+ */
+ public $table_align_class_tmpl = '';
+
+ /**
+ * Optional class prefix for fenced code block.
+ * @var string
+ */
+ public $code_class_prefix = "";
+
+ /**
+ * Class attribute for code blocks goes on the `code` tag;
+ * setting this to true will put attributes on the `pre` tag instead.
+ * @var boolean
+ */
+ public $code_attr_on_pre = false;
+
+ /**
+ * Predefined abbreviations.
+ * @var array
+ */
+ public $predef_abbr = array();
+
+ /**
+ * Only convert atx-style headers if there's a space between the header and #
+ * @var boolean
+ */
+ public $hashtag_protection = false;
+
+ /**
+ * Parser implementation
+ */
+
+ /**
+ * Constructor function. Initialize the parser object.
+ * @return void
+ */
+ public function __construct() {
+ // Add extra escapable characters before parent constructor
+ // initialize the table.
+ $this->escape_chars .= ':|';
+
+ // Insert extra document, block, and span transformations.
+ // Parent constructor will do the sorting.
+ $this->document_gamut += array(
+ "doFencedCodeBlocks" => 5,
+ "stripFootnotes" => 15,
+ "stripAbbreviations" => 25,
+ "appendFootnotes" => 50,
+ );
+ $this->block_gamut += array(
+ "doFencedCodeBlocks" => 5,
+ "doTables" => 15,
+ "doDefLists" => 45,
+ );
+ $this->span_gamut += array(
+ "doFootnotes" => 5,
+ "doAbbreviations" => 70,
+ );
+
+ $this->enhanced_ordered_list = true;
+ parent::__construct();
+ }
+
+
+ /**
+ * Extra variables used during extra transformations.
+ * @var array
+ */
+ protected $footnotes = array();
+ protected $footnotes_ordered = array();
+ protected $footnotes_ref_count = array();
+ protected $footnotes_numbers = array();
+ protected $abbr_desciptions = array();
+ /** @var string */
+ protected $abbr_word_re = '';
+
+ /**
+ * Give the current footnote number.
+ * @var integer
+ */
+ protected $footnote_counter = 1;
+
+ /**
+ * Setting up Extra-specific variables.
+ */
+ protected function setup() {
+ parent::setup();
+
+ $this->footnotes = array();
+ $this->footnotes_ordered = array();
+ $this->footnotes_ref_count = array();
+ $this->footnotes_numbers = array();
+ $this->abbr_desciptions = array();
+ $this->abbr_word_re = '';
+ $this->footnote_counter = 1;
+
+ foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+ if ($this->abbr_word_re)
+ $this->abbr_word_re .= '|';
+ $this->abbr_word_re .= preg_quote($abbr_word);
+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+ }
+ }
+
+ /**
+ * Clearing Extra-specific variables.
+ */
+ protected function teardown() {
+ $this->footnotes = array();
+ $this->footnotes_ordered = array();
+ $this->footnotes_ref_count = array();
+ $this->footnotes_numbers = array();
+ $this->abbr_desciptions = array();
+ $this->abbr_word_re = '';
+
+ parent::teardown();
+ }
+
+
+ /**
+ * Extra attribute parser
+ */
+
+ /**
+ * Expression to use to catch attributes (includes the braces)
+ * @var string
+ */
+ protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
+
+ /**
+ * Expression to use when parsing in a context when no capture is desired
+ * @var string
+ */
+ protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
+
+ /**
+ * Parse attributes caught by the $this->id_class_attr_catch_re expression
+ * and return the HTML-formatted list of attributes.
+ *
+ * Currently supported attributes are .class and #id.
+ *
+ * In addition, this method also supports supplying a default Id value,
+ * which will be used to populate the id attribute in case it was not
+ * overridden.
+ * @param string $tag_name
+ * @param string $attr
+ * @param mixed $defaultIdValue
+ * @param array $classes
+ * @return string
+ */
+ protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) {
+ if (empty($attr) && !$defaultIdValue && empty($classes)) return "";
+
+ // Split on components
+ preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
+ $elements = $matches[0];
+
+ // Handle classes and IDs (only first ID taken into account)
+ $attributes = array();
+ $id = false;
+ foreach ($elements as $element) {
+ if ($element{0} == '.') {
+ $classes[] = substr($element, 1);
+ } else if ($element{0} == '#') {
+ if ($id === false) $id = substr($element, 1);
+ } else if (strpos($element, '=') > 0) {
+ $parts = explode('=', $element, 2);
+ $attributes[] = $parts[0] . '="' . $parts[1] . '"';
+ }
+ }
+
+ if (!$id) $id = $defaultIdValue;
+
+ // Compose attributes as string
+ $attr_str = "";
+ if (!empty($id)) {
+ $attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
+ }
+ if (!empty($classes)) {
+ $attr_str .= ' class="'. implode(" ", $classes) . '"';
+ }
+ if (!$this->no_markup && !empty($attributes)) {
+ $attr_str .= ' '.implode(" ", $attributes);
+ }
+ return $attr_str;
+ }
+
+ /**
+ * Strips link definitions from text, stores the URLs and titles in
+ * hash references.
+ * @param string $text
+ * @return string
+ */
+ protected function stripLinkDefinitions($text) {
+ $less_than_tab = $this->tab_width - 1;
+
+ // Link defs are in the form: ^[id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ [ ]*
+ (?:
+ <(.+?)> # url = $2
+ |
+ (\S+?) # url = $3
+ )
+ [ ]*
+ \n? # maybe one newline
+ [ ]*
+ (?:
+ (?<=\s) # lookbehind for whitespace
+ ["(]
+ (.*?) # title = $4
+ [")]
+ [ ]*
+ )? # title is optional
+ (?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr
+ (?:\n+|\Z)
+ }xm',
+ array($this, '_stripLinkDefinitions_callback'),
+ $text);
+ return $text;
+ }
+
+ /**
+ * Strip link definition callback
+ * @param array $matches
+ * @return string
+ */
+ protected function _stripLinkDefinitions_callback($matches) {
+ $link_id = strtolower($matches[1]);
+ $url = $matches[2] == '' ? $matches[3] : $matches[2];
+ $this->urls[$link_id] = $url;
+ $this->titles[$link_id] =& $matches[4];
+ $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
+ return ''; // String that will replace the block
+ }
+
+
+ /**
+ * HTML block parser
+ */
+
+ /**
+ * Tags that are always treated as block tags
+ * @var string
+ */
+ protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure';
+
+ /**
+ * Tags treated as block tags only if the opening tag is alone on its line
+ * @var string
+ */
+ protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
+
+ /**
+ * Tags where markdown="1" default to span mode:
+ * @var string
+ */
+ protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+
+ /**
+ * Tags which must not have their contents modified, no matter where
+ * they appear
+ * @var string
+ */
+ protected $clean_tags_re = 'script|style|math|svg';
+
+ /**
+ * Tags that do not need to be closed.
+ * @var string
+ */
+ protected $auto_close_tags_re = 'hr|img|param|source|track';
+
+ /**
+ * Hashify HTML Blocks and "clean tags".
+ *
+ * We only want to do this for block-level HTML tags, such as headers,
+ * lists, and tables. That's because we still want to wrap <p>s around
+ * "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+ * phrase emphasis, and spans. The list of tags we're looking for is
+ * hard-coded.
+ *
+ * This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+ * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
+ * attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
+ * _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+ * These two functions are calling each other. It's recursive!
+ * @param string $text
+ * @return string
+ */
+ protected function hashHTMLBlocks($text) {
+ if ($this->no_markup) {
+ return $text;
+ }
+
+ // Call the HTML-in-Markdown hasher.
+ list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+
+ return $text;
+ }
+
+ /**
+ * Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+ *
+ * * $indent is the number of space to be ignored when checking for code
+ * blocks. This is important because if we don't take the indent into
+ * account, something like this (which looks right) won't work as expected:
+ *
+ * <div>
+ * <div markdown="1">
+ * Hello World. <-- Is this a Markdown code block or text?
+ * </div> <-- Is this a Markdown code block or a real tag?
+ * <div>
+ *
+ * If you don't like this, just don't indent the tag on which
+ * you apply the markdown="1" attribute.
+ *
+ * * If $enclosing_tag_re is not empty, stops at the first unmatched closing
+ * tag with that name. Nested tags supported.
+ *
+ * * If $span is true, text inside must treated as span. So any double
+ * newline will be replaced by a single newline so that it does not create
+ * paragraphs.
+ *
+ * Returns an array of that form: ( processed text , remaining text )
+ *
+ * @param string $text
+ * @param integer $indent
+ * @param string $enclosing_tag_re
+ * @param boolean $span
+ * @return array
+ */
+ protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
+ $enclosing_tag_re = '', $span = false)
+ {
+
+ if ($text === '') return array('', '');
+
+ // Regex to check for the presense of newlines around a block tag.
+ $newline_before_re = '/(?:^\n?|\n\n)*$/';
+ $newline_after_re =
+ '{
+ ^ # Start of text following the tag.
+ (?>[ ]*<!--.*?-->)? # Optional comment.
+ [ ]*\n # Must be followed by newline.
+ }xs';
+
+ // Regex to match any tag.
+ $block_tag_re =
+ '{
+ ( # $2: Capture whole tag.
+ </? # Any opening or closing tag.
+ (?> # Tag name.
+ ' . $this->block_tags_re . ' |
+ ' . $this->context_block_tags_re . ' |
+ ' . $this->clean_tags_re . ' |
+ (?!\s)'.$enclosing_tag_re . '
+ )
+ (?:
+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+ (?>
+ ".*?" | # Double quotes (can contain `>`)
+ \'.*?\' | # Single quotes (can contain `>`)
+ .+? # Anything but quotes and `>`.
+ )*?
+ )?
+ > # End of tag.
+ |
+ <!-- .*? --> # HTML Comment
+ |
+ <\?.*?\?> | <%.*?%> # Processing instruction
+ |
+ <!\[CDATA\[.*?\]\]> # CData Block
+ ' . ( !$span ? ' # If not in span.
+ |
+ # Indented code block
+ (?: ^[ ]*\n | ^ | \n[ ]*\n )
+ [ ]{' . ($indent + 4) . '}[^\n]* \n
+ (?>
+ (?: [ ]{' . ($indent + 4) . '}[^\n]* | [ ]* ) \n
+ )*
+ |
+ # Fenced code block marker
+ (?<= ^ | \n )
+ [ ]{0,' . ($indent + 3) . '}(?:~{3,}|`{3,})
+ [ ]*
+ (?: \.?[-_:a-zA-Z0-9]+ )? # standalone class name
+ [ ]*
+ (?: ' . $this->id_class_attr_nocatch_re . ' )? # extra attributes
+ [ ]*
+ (?= \n )
+ ' : '' ) . ' # End (if not is span).
+ |
+ # Code span marker
+ # Note, this regex needs to go after backtick fenced
+ # code blocks but it should also be kept outside of the
+ # "if not in span" condition adding backticks to the parser
+ `+
+ )
+ }xs';
+
+
+ $depth = 0; // Current depth inside the tag tree.
+ $parsed = ""; // Parsed text that will be returned.
+
+ // Loop through every tag until we find the closing tag of the parent
+ // or loop until reaching the end of text if no parent tag specified.
+ do {
+ // Split the text using the first $tag_match pattern found.
+ // Text before pattern will be first in the array, text after
+ // pattern will be at the end, and between will be any catches made
+ // by the pattern.
+ $parts = preg_split($block_tag_re, $text, 2,
+ PREG_SPLIT_DELIM_CAPTURE);
+
+ // If in Markdown span mode, add a empty-string span-level hash
+ // after each newline to prevent triggering any block element.
+ if ($span) {
+ $void = $this->hashPart("", ':');
+ $newline = "\n$void";
+ $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+ }
+
+ $parsed .= $parts[0]; // Text before current tag.
+
+ // If end of $text has been reached. Stop loop.
+ if (count($parts) < 3) {
+ $text = "";
+ break;
+ }
+
+ $tag = $parts[1]; // Tag to handle.
+ $text = $parts[2]; // Remaining text after current tag.
+ $tag_re = preg_quote($tag); // For use in a regular expression.
+
+ // Check for: Fenced code block marker.
+ // Note: need to recheck the whole tag to disambiguate backtick
+ // fences from code spans
+ if (preg_match('{^\n?([ ]{0,' . ($indent + 3) . '})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:' . $this->id_class_attr_nocatch_re . ')?[ ]*\n?$}', $tag, $capture)) {
+ // Fenced code block marker: find matching end marker.
+ $fence_indent = strlen($capture[1]); // use captured indent in re
+ $fence_re = $capture[2]; // use captured fence in re
+ if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text,
+ $matches))
+ {
+ // End marker found: pass text unchanged until marker.
+ $parsed .= $tag . $matches[0];
+ $text = substr($text, strlen($matches[0]));
+ }
+ else {
+ // No end marker: just skip it.
+ $parsed .= $tag;
+ }
+ }
+ // Check for: Indented code block.
+ else if ($tag{0} == "\n" || $tag{0} == " ") {
+ // Indented code block: pass it unchanged, will be handled
+ // later.
+ $parsed .= $tag;
+ }
+ // Check for: Code span marker
+ // Note: need to check this after backtick fenced code blocks
+ else if ($tag{0} == "`") {
+ // Find corresponding end marker.
+ $tag_re = preg_quote($tag);
+ if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)' . $tag_re . '(?!`)}',
+ $text, $matches))
+ {
+ // End marker found: pass text unchanged until marker.
+ $parsed .= $tag . $matches[0];
+ $text = substr($text, strlen($matches[0]));
+ }
+ else {
+ // Unmatched marker: just skip it.
+ $parsed .= $tag;
+ }
+ }
+ // Check for: Opening Block level tag or
+ // Opening Context Block tag (like ins and del)
+ // used as a block tag (tag is alone on it's line).
+ else if (preg_match('{^<(?:' . $this->block_tags_re . ')\b}', $tag) ||
+ ( preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
+ preg_match($newline_before_re, $parsed) &&
+ preg_match($newline_after_re, $text) )
+ )
+ {
+ // Need to parse tag and following text using the HTML parser.
+ list($block_text, $text) =
+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+
+ // Make sure it stays outside of any paragraph by adding newlines.
+ $parsed .= "\n\n$block_text\n\n";
+ }
+ // Check for: Clean tag (like script, math)
+ // HTML Comments, processing instructions.
+ else if (preg_match('{^<(?:' . $this->clean_tags_re . ')\b}', $tag) ||
+ $tag{1} == '!' || $tag{1} == '?')
+ {
+ // Need to parse tag and following text using the HTML parser.
+ // (don't check for markdown attribute)
+ list($block_text, $text) =
+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+
+ $parsed .= $block_text;
+ }
+ // Check for: Tag with same name as enclosing tag.
+ else if ($enclosing_tag_re !== '' &&
+ // Same name as enclosing tag.
+ preg_match('{^</?(?:' . $enclosing_tag_re . ')\b}', $tag))
+ {
+ // Increase/decrease nested tag count.
+ if ($tag{1} == '/') $depth--;
+ else if ($tag{strlen($tag)-2} != '/') $depth++;
+
+ if ($depth < 0) {
+ // Going out of parent element. Clean up and break so we
+ // return to the calling function.
+ $text = $tag . $text;
+ break;
+ }
+
+ $parsed .= $tag;
+ }
+ else {
+ $parsed .= $tag;
+ }
+ } while ($depth >= 0);
+
+ return array($parsed, $text);
+ }
+
+ /**
+ * Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+ *
+ * * Calls $hash_method to convert any blocks.
+ * * Stops when the first opening tag closes.
+ * * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+ * (it is not inside clean tags)
+ *
+ * Returns an array of that form: ( processed text , remaining text )
+ * @param string $text
+ * @param string $hash_method
+ * @param string $md_attr
+ * @return array
+ */
+ protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+ if ($text === '') return array('', '');
+
+ // Regex to match `markdown` attribute inside of a tag.
+ $markdown_attr_re = '
+ {
+ \s* # Eat whitespace before the `markdown` attribute
+ markdown
+ \s*=\s*
+ (?>
+ (["\']) # $1: quote delimiter
+ (.*?) # $2: attribute value
+ \1 # matching delimiter
+ |
+ ([^\s>]*) # $3: unquoted attribute value
+ )
+ () # $4: make $3 always defined (avoid warnings)
+ }xs';
+
+ // Regex to match any tag.
+ $tag_re = '{
+ ( # $2: Capture whole tag.
+ </? # Any opening or closing tag.
+ [\w:$]+ # Tag name.
+ (?:
+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+ (?>
+ ".*?" | # Double quotes (can contain `>`)
+ \'.*?\' | # Single quotes (can contain `>`)
+ .+? # Anything but quotes and `>`.
+ )*?
+ )?
+ > # End of tag.
+ |
+ <!-- .*? --> # HTML Comment
+ |
+ <\?.*?\?> | <%.*?%> # Processing instruction
+ |
+ <!\[CDATA\[.*?\]\]> # CData Block
+ )
+ }xs';
+
+ $original_text = $text; // Save original text in case of faliure.
+
+ $depth = 0; // Current depth inside the tag tree.
+ $block_text = ""; // Temporary text holder for current text.
+ $parsed = ""; // Parsed text that will be returned.
+
+ // Get the name of the starting tag.
+ // (This pattern makes $base_tag_name_re safe without quoting.)
+ if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+ $base_tag_name_re = $matches[1];
+
+ // Loop through every tag until we find the corresponding closing tag.
+ do {
+ // Split the text using the first $tag_match pattern found.
+ // Text before pattern will be first in the array, text after
+ // pattern will be at the end, and between will be any catches made
+ // by the pattern.
+ $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ if (count($parts) < 3) {
+ // End of $text reached with unbalenced tag(s).
+ // In that case, we return original text unchanged and pass the
+ // first character as filtered to prevent an infinite loop in the
+ // parent function.
+ return array($original_text{0}, substr($original_text, 1));
+ }
+
+ $block_text .= $parts[0]; // Text before current tag.
+ $tag = $parts[1]; // Tag to handle.
+ $text = $parts[2]; // Remaining text after current tag.
+
+ // Check for: Auto-close tag (like <hr/>)
+ // Comments and Processing Instructions.
+ if (preg_match('{^</?(?:' . $this->auto_close_tags_re . ')\b}', $tag) ||
+ $tag{1} == '!' || $tag{1} == '?')
+ {
+ // Just add the tag to the block as if it was text.
+ $block_text .= $tag;
+ }
+ else {
+ // Increase/decrease nested tag count. Only do so if
+ // the tag's name match base tag's.
+ if (preg_match('{^</?' . $base_tag_name_re . '\b}', $tag)) {
+ if ($tag{1} == '/') $depth--;
+ else if ($tag{strlen($tag)-2} != '/') $depth++;
+ }
+
+ // Check for `markdown="1"` attribute and handle it.
+ if ($md_attr &&
+ preg_match($markdown_attr_re, $tag, $attr_m) &&
+ preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+ {
+ // Remove `markdown` attribute from opening tag.
+ $tag = preg_replace($markdown_attr_re, '', $tag);
+
+ // Check if text inside this tag must be parsed in span mode.
+ $this->mode = $attr_m[2] . $attr_m[3];
+ $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+ preg_match('{^<(?:' . $this->contain_span_tags_re . ')\b}', $tag);
+
+ // Calculate indent before tag.
+ if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+ $strlen = $this->utf8_strlen;
+ $indent = $strlen($matches[1], 'UTF-8');
+ } else {
+ $indent = 0;
+ }
+
+ // End preceding block with this tag.
+ $block_text .= $tag;
+ $parsed .= $this->$hash_method($block_text);
+
+ // Get enclosing tag name for the ParseMarkdown function.
+ // (This pattern makes $tag_name_re safe without quoting.)
+ preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+ $tag_name_re = $matches[1];
+
+ // Parse the content using the HTML-in-Markdown parser.
+ list ($block_text, $text)
+ = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
+ $tag_name_re, $span_mode);
+
+ // Outdent markdown text.
+ if ($indent > 0) {
+ $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
+ $block_text);
+ }
+
+ // Append tag content to parsed text.
+ if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
+ else $parsed .= "$block_text";
+
+ // Start over with a new block.
+ $block_text = "";
+ }
+ else $block_text .= $tag;
+ }
+
+ } while ($depth > 0);
+
+ // Hash last block text that wasn't processed inside the loop.
+ $parsed .= $this->$hash_method($block_text);
+
+ return array($parsed, $text);
+ }
+
+ /**
+ * Called whenever a tag must be hashed when a function inserts a "clean" tag
+ * in $text, it passes through this function and is automaticaly escaped,
+ * blocking invalid nested overlap.
+ * @param string $text
+ * @return string
+ */
+ protected function hashClean($text) {
+ return $this->hashPart($text, 'C');
+ }
+
+ /**
+ * Turn Markdown link shortcuts into XHTML <a> tags.
+ * @param string $text
+ * @return string
+ */
+ protected function doAnchors($text) {
+ if ($this->in_anchor) {
+ return $text;
+ }
+ $this->in_anchor = true;
+
+ // First, handle reference-style links: [link text] [id]
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ (' . $this->nested_brackets_re . ') # link text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+ )
+ }xs',
+ array($this, '_doAnchors_reference_callback'), $text);
+
+ // Next, inline-style links: [link text](url "optional title")
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ (' . $this->nested_brackets_re . ') # link text = $2
+ \]
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(.+?)> # href = $3
+ |
+ (' . $this->nested_url_parenthesis_re . ') # href = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # Title = $7
+ \6 # matching quote
+ [ \n]* # ignore any spaces/tabs between closing quote and )
+ )? # title is optional
+ \)
+ (?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes
+ )
+ }xs',
+ array($this, '_doAnchors_inline_callback'), $text);
+
+ // Last, handle reference-style shortcuts: [link text]
+ // These must come last in case you've also got [link text][1]
+ // or [link text](/foo)
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ([^\[\]]+) # link text = $2; can\'t contain [ or ]
+ \]
+ )
+ }xs',
+ array($this, '_doAnchors_reference_callback'), $text);
+
+ $this->in_anchor = false;
+ return $text;
+ }
+
+ /**
+ * Callback for reference anchors
+ * @param array $matches
+ * @return string
+ */
+ protected function _doAnchors_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $matches[2];
+ $link_id =& $matches[3];
+
+ if ($link_id == "") {
+ // for shortcut links like [this][] or [this].
+ $link_id = $link_text;
+ }
+
+ // lower-case and turn embedded newlines into spaces
+ $link_id = strtolower($link_id);
+ $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+ if (isset($this->urls[$link_id])) {
+ $url = $this->urls[$link_id];
+ $url = $this->encodeURLAttribute($url);
+
+ $result = "<a href=\"$url\"";
+ if ( isset( $this->titles[$link_id] ) ) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ if (isset($this->ref_attr[$link_id]))
+ $result .= $this->ref_attr[$link_id];
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text</a>";
+ $result = $this->hashPart($result);
+ }
+ else {
+ $result = $whole_match;
+ }
+ return $result;
+ }
+
+ /**
+ * Callback for inline anchors
+ * @param array $matches
+ * @return string
+ */
+ protected function _doAnchors_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $this->runSpanGamut($matches[2]);
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+ $attr = $this->doExtraAttributes("a", $dummy =& $matches[8]);
+
+ // if the URL was of the form <s p a c e s> it got caught by the HTML
+ // tag parser and hashed. Need to reverse the process before using the URL.
+ $unhashed = $this->unhash($url);
+ if ($unhashed != $url)
+ $url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
+
+ $url = $this->encodeURLAttribute($url);
+
+ $result = "<a href=\"$url\"";
+ if (isset($title)) {
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ $result .= $attr;
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text</a>";
+
+ return $this->hashPart($result);
+ }
+
+ /**
+ * Turn Markdown image shortcuts into <img> tags.
+ * @param string $text
+ * @return string
+ */
+ protected function doImages($text) {
+ // First, handle reference-style labeled images: ![alt text][id]
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ (' . $this->nested_brackets_re . ') # alt text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+
+ )
+ }xs',
+ array($this, '_doImages_reference_callback'), $text);
+
+ // Next, handle inline images: 
+ // Don't forget: encode * and _
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ (' . $this->nested_brackets_re . ') # alt text = $2
+ \]
+ \s? # One optional whitespace character
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(\S*)> # src url = $3
+ |
+ (' . $this->nested_url_parenthesis_re . ') # src url = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # title = $7
+ \6 # matching quote
+ [ \n]*
+ )? # title is optional
+ \)
+ (?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes
+ )
+ }xs',
+ array($this, '_doImages_inline_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Callback for referenced images
+ * @param array $matches
+ * @return string
+ */
+ protected function _doImages_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $link_id = strtolower($matches[3]);
+
+ if ($link_id == "") {
+ $link_id = strtolower($alt_text); // for shortcut links like ![this][].
+ }
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ if (isset($this->urls[$link_id])) {
+ $url = $this->encodeURLAttribute($this->urls[$link_id]);
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
+ if (isset($this->titles[$link_id])) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ if (isset($this->ref_attr[$link_id]))
+ $result .= $this->ref_attr[$link_id];
+ $result .= $this->empty_element_suffix;
+ $result = $this->hashPart($result);
+ }
+ else {
+ // If there's no such link ID, leave intact:
+ $result = $whole_match;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Callback for inline images
+ * @param array $matches
+ * @return string
+ */
+ protected function _doImages_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+ $attr = $this->doExtraAttributes("img", $dummy =& $matches[8]);
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ $url = $this->encodeURLAttribute($url);
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
+ if (isset($title)) {
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\""; // $title already quoted
+ }
+ $result .= $attr;
+ $result .= $this->empty_element_suffix;
+
+ return $this->hashPart($result);
+ }
+
+ /**
+ * Process markdown headers. Redefined to add ID and class attribute support.
+ * @param string $text
+ * @return string
+ */
+ protected function doHeaders($text) {
+ // Setext-style headers:
+ // Header 1 {#header1}
+ // ========
+ //
+ // Header 2 {#header2 .class1 .class2}
+ // --------
+ //
+ $text = preg_replace_callback(
+ '{
+ (^.+?) # $1: Header text
+ (?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes
+ [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
+ }mx',
+ array($this, '_doHeaders_callback_setext'), $text);
+
+ // atx-style headers:
+ // # Header 1 {#header1}
+ // ## Header 2 {#header2}
+ // ## Header 2 with closing hashes ## {#header3.class1.class2}
+ // ...
+ // ###### Header 6 {.class2}
+ //
+ $text = preg_replace_callback('{
+ ^(\#{1,6}) # $1 = string of #\'s
+ [ ]'.($this->hashtag_protection ? '+' : '*').'
+ (.+?) # $2 = Header text
+ [ ]*
+ \#* # optional closing #\'s (not counted)
+ (?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes
+ [ ]*
+ \n+
+ }xm',
+ array($this, '_doHeaders_callback_atx'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Callback for setext headers
+ * @param array $matches
+ * @return string
+ */
+ protected function _doHeaders_callback_setext($matches) {
+ if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) {
+ return $matches[0];
+ }
+
+ $level = $matches[3]{0} == '=' ? 1 : 2;
+
+ $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
+
+ $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
+ $block = "<h$level$attr>" . $this->runSpanGamut($matches[1]) . "</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+ /**
+ * Callback for atx headers
+ * @param array $matches
+ * @return string
+ */
+ protected function _doHeaders_callback_atx($matches) {
+ $level = strlen($matches[1]);
+
+ $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
+ $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
+ $block = "<h$level$attr>" . $this->runSpanGamut($matches[2]) . "</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+ /**
+ * Form HTML tables.
+ * @param string $text
+ * @return string
+ */
+ protected function doTables($text) {
+ $less_than_tab = $this->tab_width - 1;
+ // Find tables with leading pipe.
+ //
+ // | Header 1 | Header 2
+ // | -------- | --------
+ // | Cell 1 | Cell 2
+ // | Cell 3 | Cell 4
+ $text = preg_replace_callback('
+ {
+ ^ # Start of a line
+ [ ]{0,' . $less_than_tab . '} # Allowed whitespace.
+ [|] # Optional leading pipe (present)
+ (.+) \n # $1: Header row (at least one pipe)
+
+ [ ]{0,' . $less_than_tab . '} # Allowed whitespace.
+ [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
+
+ ( # $3: Cells
+ (?>
+ [ ]* # Allowed whitespace.
+ [|] .* \n # Row content.
+ )*
+ )
+ (?=\n|\Z) # Stop at final double newline.
+ }xm',
+ array($this, '_doTable_leadingPipe_callback'), $text);
+
+ // Find tables without leading pipe.
+ //
+ // Header 1 | Header 2
+ // -------- | --------
+ // Cell 1 | Cell 2
+ // Cell 3 | Cell 4
+ $text = preg_replace_callback('
+ {
+ ^ # Start of a line
+ [ ]{0,' . $less_than_tab . '} # Allowed whitespace.
+ (\S.*[|].*) \n # $1: Header row (at least one pipe)
+
+ [ ]{0,' . $less_than_tab . '} # Allowed whitespace.
+ ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
+
+ ( # $3: Cells
+ (?>
+ .* [|] .* \n # Row content
+ )*
+ )
+ (?=\n|\Z) # Stop at final double newline.
+ }xm',
+ array($this, '_DoTable_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Callback for removing the leading pipe for each row
+ * @param array $matches
+ * @return string
+ */
+ protected function _doTable_leadingPipe_callback($matches) {
+ $head = $matches[1];
+ $underline = $matches[2];
+ $content = $matches[3];
+
+ $content = preg_replace('/^ *[|]/m', '', $content);
+
+ return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+ }
+
+ /**
+ * Make the align attribute in a table
+ * @param string $alignname
+ * @return string
+ */
+ protected function _doTable_makeAlignAttr($alignname)
+ {
+ if (empty($this->table_align_class_tmpl)) {
+ return " align=\"$alignname\"";
+ }
+
+ $classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
+ return " class=\"$classname\"";
+ }
+
+ /**
+ * Calback for processing tables
+ * @param array $matches
+ * @return string
+ */
+ protected function _doTable_callback($matches) {
+ $head = $matches[1];
+ $underline = $matches[2];
+ $content = $matches[3];
+
+ // Remove any tailing pipes for each line.
+ $head = preg_replace('/[|] *$/m', '', $head);
+ $underline = preg_replace('/[|] *$/m', '', $underline);
+ $content = preg_replace('/[|] *$/m', '', $content);
+
+ // Reading alignement from header underline.
+ $separators = preg_split('/ *[|] */', $underline);
+ foreach ($separators as $n => $s) {
+ if (preg_match('/^ *-+: *$/', $s))
+ $attr[$n] = $this->_doTable_makeAlignAttr('right');
+ else if (preg_match('/^ *:-+: *$/', $s))
+ $attr[$n] = $this->_doTable_makeAlignAttr('center');
+ else if (preg_match('/^ *:-+ *$/', $s))
+ $attr[$n] = $this->_doTable_makeAlignAttr('left');
+ else
+ $attr[$n] = '';
+ }
+
+ // Parsing span elements, including code spans, character escapes,
+ // and inline HTML tags, so that pipes inside those gets ignored.
+ $head = $this->parseSpan($head);
+ $headers = preg_split('/ *[|] */', $head);
+ $col_count = count($headers);
+ $attr = array_pad($attr, $col_count, '');
+
+ // Write column headers.
+ $text = "<table>\n";
+ $text .= "<thead>\n";
+ $text .= "<tr>\n";
+ foreach ($headers as $n => $header)
+ $text .= " <th$attr[$n]>" . $this->runSpanGamut(trim($header)) . "</th>\n";
+ $text .= "</tr>\n";
+ $text .= "</thead>\n";
+
+ // Split content by row.
+ $rows = explode("\n", trim($content, "\n"));
+
+ $text .= "<tbody>\n";
+ foreach ($rows as $row) {
+ // Parsing span elements, including code spans, character escapes,
+ // and inline HTML tags, so that pipes inside those gets ignored.
+ $row = $this->parseSpan($row);
+
+ // Split row by cell.
+ $row_cells = preg_split('/ *[|] */', $row, $col_count);
+ $row_cells = array_pad($row_cells, $col_count, '');
+
+ $text .= "<tr>\n";
+ foreach ($row_cells as $n => $cell)
+ $text .= " <td$attr[$n]>" . $this->runSpanGamut(trim($cell)) . "</td>\n";
+ $text .= "</tr>\n";
+ }
+ $text .= "</tbody>\n";
+ $text .= "</table>";
+
+ return $this->hashBlock($text) . "\n";
+ }
+
+ /**
+ * Form HTML definition lists.
+ * @param string $text
+ * @return string
+ */
+ protected function doDefLists($text) {
+ $less_than_tab = $this->tab_width - 1;
+
+ // Re-usable pattern to match any entire dl list:
+ $whole_list_re = '(?>
+ ( # $1 = whole list
+ ( # $2
+ [ ]{0,' . $less_than_tab . '}
+ ((?>.*\S.*\n)+) # $3 = defined term
+ \n?
+ [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition
+ )
+ (?s:.+?)
+ ( # $4
+ \z
+ |
+ \n{2,}
+ (?=\S)
+ (?! # Negative lookahead for another term
+ [ ]{0,' . $less_than_tab . '}
+ (?: \S.*\n )+? # defined term
+ \n?
+ [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition
+ )
+ (?! # Negative lookahead for another definition
+ [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition
+ )
+ )
+ )
+ )'; // mx
+
+ $text = preg_replace_callback('{
+ (?>\A\n?|(?<=\n\n))
+ ' . $whole_list_re . '
+ }mx',
+ array($this, '_doDefLists_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Callback for processing definition lists
+ * @param array $matches
+ * @return string
+ */
+ protected function _doDefLists_callback($matches) {
+ // Re-usable patterns to match list item bullets and number markers:
+ $list = $matches[1];
+
+ // Turn double returns into triple returns, so that we can make a
+ // paragraph for the last item in a list, if necessary:
+ $result = trim($this->processDefListItems($list));
+ $result = "<dl>\n" . $result . "\n</dl>";
+ return $this->hashBlock($result) . "\n\n";
+ }
+
+ /**
+ * Process the contents of a single definition list, splitting it
+ * into individual term and definition list items.
+ * @param string $list_str
+ * @return string
+ */
+ protected function processDefListItems($list_str) {
+
+ $less_than_tab = $this->tab_width - 1;
+
+ // Trim trailing blank lines:
+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+ // Process definition terms.
+ $list_str = preg_replace_callback('{
+ (?>\A\n?|\n\n+) # leading line
+ ( # definition terms = $1
+ [ ]{0,' . $less_than_tab . '} # leading whitespace
+ (?!\:[ ]|[ ]) # negative lookahead for a definition
+ # mark (colon) or more whitespace.
+ (?> \S.* \n)+? # actual term (not whitespace).
+ )
+ (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
+ # with a definition mark.
+ }xm',
+ array($this, '_processDefListItems_callback_dt'), $list_str);
+
+ // Process actual definitions.
+ $list_str = preg_replace_callback('{
+ \n(\n+)? # leading line = $1
+ ( # marker space = $2
+ [ ]{0,' . $less_than_tab . '} # whitespace before colon
+ \:[ ]+ # definition mark (colon)
+ )
+ ((?s:.+?)) # definition text = $3
+ (?= \n+ # stop at next definition mark,
+ (?: # next term or end of text
+ [ ]{0,' . $less_than_tab . '} \:[ ] |
+ <dt> | \z
+ )
+ )
+ }xm',
+ array($this, '_processDefListItems_callback_dd'), $list_str);
+
+ return $list_str;
+ }
+
+ /**
+ * Callback for <dt> elements in definition lists
+ * @param array $matches
+ * @return string
+ */
+ protected function _processDefListItems_callback_dt($matches) {
+ $terms = explode("\n", trim($matches[1]));
+ $text = '';
+ foreach ($terms as $term) {
+ $term = $this->runSpanGamut(trim($term));
+ $text .= "\n<dt>" . $term . "</dt>";
+ }
+ return $text . "\n";
+ }
+
+ /**
+ * Callback for <dd> elements in definition lists
+ * @param array $matches
+ * @return string
+ */
+ protected function _processDefListItems_callback_dd($matches) {
+ $leading_line = $matches[1];
+ $marker_space = $matches[2];
+ $def = $matches[3];
+
+ if ($leading_line || preg_match('/\n{2,}/', $def)) {
+ // Replace marker with the appropriate whitespace indentation
+ $def = str_repeat(' ', strlen($marker_space)) . $def;
+ $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+ $def = "\n". $def ."\n";
+ }
+ else {
+ $def = rtrim($def);
+ $def = $this->runSpanGamut($this->outdent($def));
+ }
+
+ return "\n<dd>" . $def . "</dd>\n";
+ }
+
+ /**
+ * Adding the fenced code block syntax to regular Markdown:
+ *
+ * ~~~
+ * Code block
+ * ~~~
+ *
+ * @param string $text
+ * @return string
+ */
+ protected function doFencedCodeBlocks($text) {
+
+ $less_than_tab = $this->tab_width;
+
+ $text = preg_replace_callback('{
+ (?:\n|\A)
+ # 1: Opening marker
+ (
+ (?:~{3,}|`{3,}) # 3 or more tildes/backticks.
+ )
+ [ ]*
+ (?:
+ \.?([-_:a-zA-Z0-9]+) # 2: standalone class name
+ )?
+ [ ]*
+ (?:
+ ' . $this->id_class_attr_catch_re . ' # 3: Extra attributes
+ )?
+ [ ]* \n # Whitespace and newline following marker.
+
+ # 4: Content
+ (
+ (?>
+ (?!\1 [ ]* \n) # Not a closing marker.
+ .*\n+
+ )+
+ )
+
+ # Closing marker.
+ \1 [ ]* (?= \n )
+ }xm',
+ array($this, '_doFencedCodeBlocks_callback'), $text);
+
+ return $text;
+ }
+
+ /**
+ * Callback to process fenced code blocks
+ * @param array $matches
+ * @return string
+ */
+ protected function _doFencedCodeBlocks_callback($matches) {
+ $classname =& $matches[2];
+ $attrs =& $matches[3];
+ $codeblock = $matches[4];
+
+ if ($this->code_block_content_func) {
+ $codeblock = call_user_func($this->code_block_content_func, $codeblock, $classname);
+ } else {
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+ }
+
+ $codeblock = preg_replace_callback('/^\n+/',
+ array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
+
+ $classes = array();
+ if ($classname != "") {
+ if ($classname{0} == '.')
+ $classname = substr($classname, 1);
+ $classes[] = $this->code_class_prefix . $classname;
+ }
+ $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes);
+ $pre_attr_str = $this->code_attr_on_pre ? $attr_str : '';
+ $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
+ $codeblock = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
+
+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
+ }
+
+ /**
+ * Replace new lines in fenced code blocks
+ * @param array $matches
+ * @return string
+ */
+ protected function _doFencedCodeBlocks_newlines($matches) {
+ return str_repeat("<br$this->empty_element_suffix",
+ strlen($matches[0]));
+ }
+
+ /**
+ * Redefining emphasis markers so that emphasis by underscore does not
+ * work in the middle of a word.
+ * @var array
+ */
+ protected $em_relist = array(
+ '' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
+ '*' => '(?<![\s*])\*(?!\*)',
+ '_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
+ );
+ protected $strong_relist = array(
+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
+ '**' => '(?<![\s*])\*\*(?!\*)',
+ '__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
+ );
+ protected $em_strong_relist = array(
+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
+ '***' => '(?<![\s*])\*\*\*(?!\*)',
+ '___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
+ );
+
+ /**
+ * Parse text into paragraphs
+ * @param string $text String to process in paragraphs
+ * @param boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
+ * @return string HTML output
+ */
+ protected function formParagraphs($text, $wrap_in_p = true) {
+ // Strip leading and trailing lines:
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+ // Wrap <p> tags and unhashify HTML blocks
+ foreach ($grafs as $key => $value) {
+ $value = trim($this->runSpanGamut($value));
+
+ // Check if this should be enclosed in a paragraph.
+ // Clean tag hashes & block tag hashes are left alone.
+ $is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+
+ if ($is_p) {
+ $value = "<p>$value</p>";
+ }
+ $grafs[$key] = $value;
+ }
+
+ // Join grafs in one text, then unhash HTML tags.
+ $text = implode("\n\n", $grafs);
+
+ // Finish by removing any tag hashes still present in $text.
+ $text = $this->unhash($text);
+
+ return $text;
+ }
+
+
+ /**
+ * Footnotes - Strips link definitions from text, stores the URLs and
+ * titles in hash references.
+ * @param string $text
+ * @return string
+ */
+ protected function stripFootnotes($text) {
+ $less_than_tab = $this->tab_width - 1;
+
+ // Link defs are in the form: [^id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,' . $less_than_tab . '}\[\^(.+?)\][ ]?: # note_id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ ( # text = $2 (no blank lines allowed)
+ (?:
+ .+ # actual text
+ |
+ \n # newlines but
+ (?!\[.+?\][ ]?:\s)# negative lookahead for footnote or link definition marker.
+ (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
+ # by non-indented content
+ )*
+ )
+ }xm',
+ array($this, '_stripFootnotes_callback'),
+ $text);
+ return $text;
+ }
+
+ /**
+ * Callback for stripping footnotes
+ * @param array $matches
+ * @return string
+ */
+ protected function _stripFootnotes_callback($matches) {
+ $note_id = $this->fn_id_prefix . $matches[1];
+ $this->footnotes[$note_id] = $this->outdent($matches[2]);
+ return ''; // String that will replace the block
+ }
+
+ /**
+ * Replace footnote references in $text [^id] with a special text-token
+ * which will be replaced by the actual footnote marker in appendFootnotes.
+ * @param string $text
+ * @return string
+ */
+ protected function doFootnotes($text) {
+ if (!$this->in_anchor) {
+ $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+ }
+ return $text;
+ }
+
+ /**
+ * Append footnote list to text
+ * @param string $text
+ * @return string
+ */
+ protected function appendFootnotes($text) {
+ $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+ array($this, '_appendFootnotes_callback'), $text);
+
+ if (!empty($this->footnotes_ordered)) {
+ $text .= "\n\n";
+ $text .= "<div class=\"footnotes\" role=\"doc-endnotes\">\n";
+ $text .= "<hr" . $this->empty_element_suffix . "\n";
+ $text .= "<ol>\n\n";
+
+ $attr = "";
+ if ($this->fn_backlink_class != "") {
+ $class = $this->fn_backlink_class;
+ $class = $this->encodeAttribute($class);
+ $attr .= " class=\"$class\"";
+ }
+ if ($this->fn_backlink_title != "") {
+ $title = $this->fn_backlink_title;
+ $title = $this->encodeAttribute($title);
+ $attr .= " title=\"$title\"";
+ $attr .= " aria-label=\"$title\"";
+ }
+ $attr .= " role=\"doc-backlink\"";
+ $backlink_text = $this->fn_backlink_html;
+ $num = 0;
+
+ while (!empty($this->footnotes_ordered)) {
+ $footnote = reset($this->footnotes_ordered);
+ $note_id = key($this->footnotes_ordered);
+ unset($this->footnotes_ordered[$note_id]);
+ $ref_count = $this->footnotes_ref_count[$note_id];
+ unset($this->footnotes_ref_count[$note_id]);
+ unset($this->footnotes[$note_id]);
+
+ $footnote .= "\n"; // Need to append newline before parsing.
+ $footnote = $this->runBlockGamut("$footnote\n");
+ $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+ array($this, '_appendFootnotes_callback'), $footnote);
+
+ $attr = str_replace("%%", ++$num, $attr);
+ $note_id = $this->encodeAttribute($note_id);
+
+ // Prepare backlink, multiple backlinks if multiple references
+ $backlink = "<a href=\"#fnref:$note_id\"$attr>$backlink_text</a>";
+ for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
+ $backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>$backlink_text</a>";
+ }
+ // Add backlink to last paragraph; create new paragraph if needed.
+ if (preg_match('{</p>$}', $footnote)) {
+ $footnote = substr($footnote, 0, -4) . " $backlink</p>";
+ } else {
+ $footnote .= "\n\n<p>$backlink</p>";
+ }
+
+ $text .= "<li id=\"fn:$note_id\" role=\"doc-endnote\">\n";
+ $text .= $footnote . "\n";
+ $text .= "</li>\n\n";
+ }
+
+ $text .= "</ol>\n";
+ $text .= "</div>";
+ }
+ return $text;
+ }
+
+ /**
+ * Callback for appending footnotes
+ * @param array $matches
+ * @return string
+ */
+ protected function _appendFootnotes_callback($matches) {
+ $node_id = $this->fn_id_prefix . $matches[1];
+
+ // Create footnote marker only if it has a corresponding footnote *and*
+ // the footnote hasn't been used by another marker.
+ if (isset($this->footnotes[$node_id])) {
+ $num =& $this->footnotes_numbers[$node_id];
+ if (!isset($num)) {
+ // Transfer footnote content to the ordered list and give it its
+ // number
+ $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+ $this->footnotes_ref_count[$node_id] = 1;
+ $num = $this->footnote_counter++;
+ $ref_count_mark = '';
+ } else {
+ $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
+ }
+
+ $attr = "";
+ if ($this->fn_link_class != "") {
+ $class = $this->fn_link_class;
+ $class = $this->encodeAttribute($class);
+ $attr .= " class=\"$class\"";
+ }
+ if ($this->fn_link_title != "") {
+ $title = $this->fn_link_title;
+ $title = $this->encodeAttribute($title);
+ $attr .= " title=\"$title\"";
+ }
+ $attr .= " role=\"doc-noteref\"";
+
+ $attr = str_replace("%%", $num, $attr);
+ $node_id = $this->encodeAttribute($node_id);
+
+ return
+ "<sup id=\"fnref$ref_count_mark:$node_id\">".
+ "<a href=\"#fn:$node_id\"$attr>$num</a>".
+ "</sup>";
+ }
+
+ return "[^" . $matches[1] . "]";
+ }
+
+
+ /**
+ * Abbreviations - strips abbreviations from text, stores titles in hash
+ * references.
+ * @param string $text
+ * @return string
+ */
+ protected function stripAbbreviations($text) {
+ $less_than_tab = $this->tab_width - 1;
+
+ // Link defs are in the form: [id]*: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,' . $less_than_tab . '}\*\[(.+?)\][ ]?: # abbr_id = $1
+ (.*) # text = $2 (no blank lines allowed)
+ }xm',
+ array($this, '_stripAbbreviations_callback'),
+ $text);
+ return $text;
+ }
+
+ /**
+ * Callback for stripping abbreviations
+ * @param array $matches
+ * @return string
+ */
+ protected function _stripAbbreviations_callback($matches) {
+ $abbr_word = $matches[1];
+ $abbr_desc = $matches[2];
+ if ($this->abbr_word_re) {
+ $this->abbr_word_re .= '|';
+ }
+ $this->abbr_word_re .= preg_quote($abbr_word);
+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+ return ''; // String that will replace the block
+ }
+
+ /**
+ * Find defined abbreviations in text and wrap them in <abbr> elements.
+ * @param string $text
+ * @return string
+ */
+ protected function doAbbreviations($text) {
+ if ($this->abbr_word_re) {
+ // cannot use the /x modifier because abbr_word_re may
+ // contain significant spaces:
+ $text = preg_replace_callback('{' .
+ '(?<![\w\x1A])' .
+ '(?:' . $this->abbr_word_re . ')' .
+ '(?![\w\x1A])' .
+ '}',
+ array($this, '_doAbbreviations_callback'), $text);
+ }
+ return $text;
+ }
+
+ /**
+ * Callback for processing abbreviations
+ * @param array $matches
+ * @return string
+ */
+ protected function _doAbbreviations_callback($matches) {
+ $abbr = $matches[0];
+ if (isset($this->abbr_desciptions[$abbr])) {
+ $desc = $this->abbr_desciptions[$abbr];
+ if (empty($desc)) {
+ return $this->hashPart("<abbr>$abbr</abbr>");
+ } else {
+ $desc = $this->encodeAttribute($desc);
+ return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
+ }
+ } else {
+ return $matches[0];
+ }
+ }
+}
--- /dev/null
+<?php
+
+// Use this file if you cannot use class autoloading. It will include all the
+// files needed for the MarkdownInterface interface.
+//
+// Take a look at the PSR-0-compatible class autoloading implementation
+// in the Readme.php file if you want a simple autoloader setup.
+
+require_once dirname(__FILE__) . '/MarkdownInterface.php';
--- /dev/null
+<?php
+/**
+ * Markdown - A text-to-HTML conversion tool for web writers
+ *
+ * @package php-markdown
+ * @author Michel Fortin <michel.fortin@michelf.com>
+ * @copyright 2004-2018 Michel Fortin <https://michelf.com/projects/php-markdown/>
+ * @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
+ */
+
+namespace Michelf;
+
+/**
+ * Markdown Parser Interface
+ */
+interface MarkdownInterface {
+ /**
+ * Initialize the parser and return the result of its transform method.
+ * This will work fine for derived classes too.
+ *
+ * @api
+ *
+ * @param string $text
+ * @return string
+ */
+ public static function defaultTransform($text);
+
+ /**
+ * Main function. Performs some preprocessing on the input text
+ * and pass it through the document gamut.
+ *
+ * @api
+ *
+ * @param string $text
+ * @return string
+ */
+ public function transform($text);
+}
--- /dev/null
+PHP Markdown
+============
+
+PHP Markdown Lib 1.8.0 - 14 Jan 2018
+
+by Michel Fortin
+<https://michelf.ca/>
+
+based on Markdown by John Gruber
+<https://daringfireball.net/>
+
+
+Introduction
+------------
+
+This is a library package that includes the PHP Markdown parser and its
+sibling PHP Markdown Extra with additional features.
+
+Markdown is a text-to-HTML conversion tool for web writers. Markdown
+allows you to write using an easy-to-read, easy-to-write plain text
+format, then convert it to structurally valid XHTML (or HTML).
+
+"Markdown" is actually two things: a plain text markup syntax, and a
+software tool, originally written in Perl, that converts the plain text
+markup to HTML. PHP Markdown is a port to PHP of the original Markdown
+program by John Gruber.
+
+* [Full documentation of the Markdown syntax](<https://daringfireball.net/projects/markdown/>)
+ — Daring Fireball (John Gruber)
+* [Markdown Extra syntax additions](<https://michelf.ca/projects/php-markdown/extra/>)
+ — Michel Fortin
+
+
+Requirement
+-----------
+
+This library package requires PHP 5.3 or later.
+
+Note: The older plugin/library hybrid package for PHP Markdown and
+PHP Markdown Extra is no longer maintained but will work with PHP 4.0.5 and
+later.
+
+Before PHP 5.3.7, pcre.backtrack_limit defaults to 100 000, which is too small
+in many situations. You might need to set it to higher values. Later PHP
+releases defaults to 1 000 000, which is usually fine.
+
+
+Usage
+-----
+
+To use this library with Composer, first install it with:
+
+ $ composer require michelf/php-markdown
+
+Then include Composer's generated vendor/autoload.php to [enable autoloading]:
+
+ require 'vendor/autoload.php';
+
+Without Composer, for autoloading to work, your project needs an autoloader
+compatible with PSR-4 or PSR-0. See the included Readme.php file for a minimal
+autoloader setup. (If you cannot use autoloading, see below.)
+
+With class autoloading in place:
+
+ use Michelf\Markdown;
+ $my_html = Markdown::defaultTransform($my_text);
+
+Markdown Extra syntax is also available the same way:
+
+ use Michelf\MarkdownExtra;
+ $my_html = MarkdownExtra::defaultTransform($my_text);
+
+If you wish to use PHP Markdown with another text filter function
+built to parse HTML, you should filter the text *after* the `transform`
+function call. This is an example with [PHP SmartyPants]:
+
+ use Michelf\Markdown, Michelf\SmartyPants;
+ $my_html = Markdown::defaultTransform($my_text);
+ $my_html = SmartyPants::defaultTransform($my_html);
+
+All these examples are using the static `defaultTransform` static function
+found inside the parser class. If you want to customize the parser
+configuration, you can also instantiate it directly and change some
+configuration variables:
+
+ use Michelf\MarkdownExtra;
+ $parser = new MarkdownExtra;
+ $parser->fn_id_prefix = "post22-";
+ $my_html = $parser->transform($my_text);
+
+To learn more, see the full list of [configuration variables].
+
+ [enable autoloading]: https://getcomposer.org/doc/01-basic-usage.md#autoloading
+ [PHP SmartyPants]: https://michelf.ca/projects/php-smartypants/
+ [configuration variables]: https://michelf.ca/projects/php-markdown/configuration/
+
+
+### Usage without an autoloader
+
+If you cannot use class autoloading, you can still use `include` or `require`
+to access the parser. To load the `Michelf\Markdown` parser, do it this way:
+
+ require_once 'Michelf/Markdown.inc.php';
+
+Or, if you need the `Michelf\MarkdownExtra` parser:
+
+ require_once 'Michelf/MarkdownExtra.inc.php';
+
+While the plain `.php` files depend on autoloading to work correctly, using the
+`.inc.php` files instead will eagerly load the dependencies that would be
+loaded on demand if you were using autoloading.
+
+
+Public API and Versioning Policy
+---------------------------------
+
+Version numbers are of the form *major*.*minor*.*patch*.
+
+The public API of PHP Markdown consist of the two parser classes `Markdown`
+and `MarkdownExtra`, their constructors, the `transform` and `defaultTransform`
+functions and their configuration variables. The public API is stable for
+a given major version number. It might get additions when the minor version
+number increments.
+
+**Protected members are not considered public API.** This is unconventional
+and deserves an explanation. Incrementing the major version number every time
+the underlying implementation of something changes is going to give
+nonessential version numbers for the vast majority of people who just use the
+parser. Protected members are meant to create parser subclasses that behave in
+different ways. Very few people create parser subclasses. I don't want to
+discourage it by making everything private, but at the same time I can't
+guarantee any stable hook between versions if you use protected members.
+
+**Syntax changes** will increment the minor number for new features, and the
+patch number for small corrections. A *new feature* is something that needs a
+change in the syntax documentation. Note that since PHP Markdown Lib includes
+two parsers, a syntax change for either of them will increment the minor
+number. Also note that there is nothing perfectly backward-compatible with the
+Markdown syntax: all inputs are always valid, so new features always replace
+something that was previously legal, although generally nonsensical to do.
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+<michel.fortin@michelf.ca>
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output PHP Markdown actually produced.
+
+If you have a problem where Markdown gives you an empty result, first check
+that the backtrack limit is not too low by running `php --info | grep pcre`.
+See Installation and Requirement above for details.
+
+
+Development and Testing
+-----------------------
+
+Pull requests for fixing bugs are welcome. Proposed new features are
+going to be meticulously reviewed -- taking into account backward compatibility,
+potential side effects, and future extensibility -- before deciding on
+acceptance or rejection.
+
+If you make a pull request that includes changes to the parser please add
+tests for what is being changed to [MDTest][] and make a pull request there
+too.
+
+ [MDTest]: https://github.com/michelf/mdtest/
+
+
+Donations
+---------
+
+If you wish to make a donation that will help me devote more time to
+PHP Markdown, please visit [michelf.ca/donate] or send Bitcoin to
+[1HiuX34czvVPPdhXbUAsAu7pZcesniDCGH].
+
+ [michelf.ca/donate]: https://michelf.ca/donate/#!Thanks%20for%20PHP%20Markdown
+ [1HiuX34czvVPPdhXbUAsAu7pZcesniDCGH]: bitcoin:1HiuX34czvVPPdhXbUAsAu7pZcesniDCGH
+
+
+Version History
+---------------
+
+PHP Markdown Lib 1.8.0 (14 Jan 2018)
+
+* Autoloading with Composer now uses PSR-4.
+
+* HTML output for Markdown Extra footnotes now include `role` attributes
+ with values from [WAI-ARIA](https://www.w3.org/TR/dpub-aria/) to
+ make them more accessible.
+ (Thanks to Tobias Bengfort)
+
+* In Markdown Extra, added the `hashtag_protection` configuration variable.
+ When set to `true` it prevents ATX-style headers with no space after the initial
+ hash from being interpreted as headers. This way your precious hashtags
+ are preserved.
+ (Thanks to Jaussoin Timothée for the implementation.)
+
+
+PHP Markdown Lib 1.7.0 (29 Oct 2016)
+
+* Added a `hard_wrap` configuration variable to make all newline characters
+ in the text become `<br>` tags in the HTML output. By default, according
+ to the standard Markdown syntax these newlines are ignored unless they a
+ preceded by two spaces. Thanks to Jonathan Cohlmeyer for the implementation.
+
+* Improved the parsing of list items to fix problematic cases that came to
+ light with the addition of `hard_wrap`. This should have no effect on the
+ output except span-level list items that ended with two spaces (and thus
+ ended with a line break).
+
+* Added a `code_span_content_func` configuration variable which takes a
+ function that will convert the content of the code span to HTML. This can
+ be useful to implement syntax highlighting. Although contrary to its
+ code block equivalent, there is no syntax for specifying a language.
+ Credits to styxit for the implementation.
+
+* Fixed a Markdown Extra issue where two-space-at-end-of-line hard breaks
+ wouldn't work inside of HTML block elements such as `<p markdown="1">`
+ where the element expects only span-level content.
+
+* In the parser code, switched to PHPDoc comment format. Thanks to
+ Robbie Averill for the help.
+
+
+PHP Markdown Lib 1.6.0 (23 Dec 2015)
+
+Note: this version was incorrectly released as 1.5.1 on Dec 22, a number
+that contradicted the versioning policy.
+
+* For fenced code blocks in Markdown Extra, can now set a class name for the
+ code block's language before the special attribute block. Previously, this
+ class name was only allowed in the absence of the special attribute block.
+
+* Added a `code_block_content_func` configuration variable which takes a
+ function that will convert the content of the code block to HTML. This is
+ most useful for syntax highlighting. For fenced code blocks in Markdown
+ Extra, the function has access to the language class name (the one outside
+ of the special attribute block). Credits to Mario Konrad for providing the
+ implementation.
+
+* The curled arrow character for the backlink in footnotes is now followed
+ by a Unicode variant selector to prevent it from being displayed in emoji
+ form on iOS.
+
+ Note that in older browsers the variant selector is often interpreted as a
+ separate character, making it visible after the arrow. So there is now a
+ also a `fn_backlink_html` configuration variable that can be used to set
+ the link text to something else. Credits to Dana for providing the
+ implementation.
+
+* Fixed an issue in MarkdownExtra where long header lines followed by a
+ special attribute block would hit the backtrack limit an cause an empty
+ string to be returned.
+
+
+PHP Markdown Lib 1.5.0 (1 Mar 2015)
+
+* Added the ability start ordered lists with a number different from 1 and
+ and have that reflected in the HTML output. This can be enabled with
+ the `enhanced_ordered_lists` configuration variable for the Markdown
+ parser; it is enabled by default for Markdown Extra.
+ Credits to Matt Gorle for providing the implementation.
+
+* Added the ability to insert custom HTML attributes with simple values
+ everywhere an extra attribute block is allowed (links, images, headers).
+ The value must be unquoted, cannot contains spaces and is limited to
+ alphanumeric ASCII characters.
+ Credits to Peter Droogmans for providing the implementation.
+
+* Added a `header_id_func` configuration variable which takes a function
+ that can generate an `id` attribute value from the header text.
+ Credits to Evert Pot for providing the implementation.
+
+* Added a `url_filter_func` configuration variable which takes a function
+ that can rewrite any link or image URL to something different.
+
+
+PHP Markdown Lib 1.4.1 (4 May 2014)
+
+* The HTML block parser will now treat `<figure>` as a block-level element
+ (as it should) and no longer wrap it in `<p>` or parse it's content with
+ the as Markdown syntax (although with Extra you can use `markdown="1"`
+ if you wish to use the Markdown syntax inside it).
+
+* The content of `<style>` elements will now be left alone, its content
+ won't be interpreted as Markdown.
+
+* Corrected an bug where some inline links with spaces in them would not
+ work even when surounded with angle brackets:
+
+ [link](<s p a c e s>)
+
+* Fixed an issue where email addresses with quotes in them would not always
+ have the quotes escaped in the link attribute, causing broken links (and
+ invalid HTML).
+
+* Fixed the case were a link definition following a footnote definition would
+ be swallowed by the footnote unless it was separated by a blank line.
+
+
+PHP Markdown Lib 1.4.0 (29 Nov 2013)
+
+* Added support for the `tel:` URL scheme in automatic links.
+
+ <tel:+1-111-111-1111>
+
+ It gets converted to this (note the `tel:` prefix becomes invisible):
+
+ <a href="tel:+1-111-111-1111">+1-111-111-1111</a>
+
+* Added backtick fenced code blocks to MarkdownExtra, originally from
+ Github-Flavored Markdown.
+
+* Added an interface called MarkdownInterface implemented by both
+ the Markdown and MarkdownExtra parsers. You can use the interface if
+ you want to create a mockup parser object for unit testing.
+
+* For those of you who cannot use class autoloading, you can now
+ include `Michelf/Markdown.inc.php` or `Michelf/MarkdownExtra.inc.php` (note
+ the `.inc.php` extension) to automatically include other files required
+ by the parser.
+
+
+PHP Markdown Lib 1.3 (11 Apr 2013)
+
+This is the first release of PHP Markdown Lib. This package requires PHP
+version 5.3 or later and is designed to work with PSR-0 autoloading and,
+optionally with Composer. Here is a list of the changes since
+PHP Markdown Extra 1.2.6:
+
+* Plugin interface for WordPress and other systems is no longer present in
+ the Lib package. The classic package is still available if you need it:
+ <https://michelf.ca/projects/php-markdown/classic/>
+
+* Added `public` and `protected` protection attributes, plus a section about
+ what is "public API" and what isn't in the Readme file.
+
+* Changed HTML output for footnotes: now instead of adding `rel` and `rev`
+ attributes, footnotes links have the class name `footnote-ref` and
+ backlinks `footnote-backref`.
+
+* Fixed some regular expressions to make PCRE not shout warnings about POSIX
+ collation classes (dependent on your version of PCRE).
+
+* Added optional class and id attributes to images and links using the same
+ syntax as for headers:
+
+ [link](url){#id .class}
+ {#id .class}
+
+ It work too for reference-style links and images. In this case you need
+ to put those attributes at the reference definition:
+
+ [link][linkref] or [linkref]
+ ![img][linkref]
+
+ [linkref]: url "optional title" {#id .class}
+
+* Fixed a PHP notice message triggered when some table column separator
+ markers are missing on the separator line below column headers.
+
+* Fixed a small mistake that could cause the parser to retain an invalid
+ state related to parsing links across multiple runs. This was never
+ observed (that I know of), but it's still worth fixing.
+
+
+Copyright and License
+---------------------
+
+PHP Markdown Lib
+Copyright (c) 2004-2016 Michel Fortin
+<https://michelf.ca/>
+All rights reserved.
+
+Based on Markdown
+Copyright (c) 2003-2005 John Gruber
+<https://daringfireball.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.
+
+* Neither the name "Markdown" nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as
+is" and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed. In no event shall the copyright 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.
--- /dev/null
+<?php
+
+// This file passes the content of the Readme.md file in the same directory
+// through the Markdown filter. You can adapt this sample code in any way
+// you like.
+
+// Install PSR-4-compatible class autoloader
+spl_autoload_register(function($class){
+ require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
+});
+// If using Composer, use this instead:
+//require 'vendor/autoloader.php';
+
+// Get Markdown class
+use Michelf\Markdown;
+
+// Read file and pass content through the Markdown parser
+$text = file_get_contents('Readme.md');
+$html = Markdown::defaultTransform($text);
+
+?>
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>PHP Markdown Lib - Readme</title>
+ </head>
+ <body>
+ <?php
+ // Put HTML content in the document
+ echo $html;
+ ?>
+ </body>
+</html>
--- /dev/null
+{
+ "name": "michelf/php-markdown",
+ "type": "library",
+ "description": "PHP Markdown",
+ "homepage": "https://michelf.ca/projects/php-markdown/",
+ "keywords": ["markdown"],
+ "license": "BSD-3-Clause",
+ "authors": [
+ {
+ "name": "Michel Fortin",
+ "email": "michel.fortin@michelf.ca",
+ "homepage": "https://michelf.ca/",
+ "role": "Developer"
+ },
+ {
+ "name": "John Gruber",
+ "homepage": "https://daringfireball.net/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": { "Michelf\\": "Michelf/" }
+ }
+}
+++ /dev/null
-<!--
- 🛑 DON'T REMOVE ME.
- This issue template apply to all
- - bug reports,
- - feature proposals,
- - and documentation requests
-
- Having all those informations will allow us to know exactly
- what you expect and answer you faster and precisely (answer
- that matches your Carbon version, PHP version and usage).
-
- Note: Comments between <!- - and - -> won't appear in the final
- issue (See [Preview] tab).
--->
-Hello,
-
-I encountered an issue with the following code:
-```php
-echo Carbon::parse('2018-06-01')->subDay()->month;
-```
-
-Carbon version: **PUT HERE YOUR COMPOSER CARBON VERSION**
-
-PHP version: **PUT HERE YOUR PHP VERSION**
-
-<!--
- Run the command `composer show nesbot/carbon`
- to get "versions"
- Use `echo phpversion();`
- to get PHP version.
-
- Some issues can depends on your context, settings,
- macros, timezone, language. So to be sure the code
- you give is enough to reproduce your bug, try it
- first in:
- https://try-carbon.herokuapp.com/?theme=xcode&export&embed
-
- You can use the [Options] button to change the version
- then when you get the bug with this editor, you can use
- the [Export] button, copy the link of the opened tab,
- then paste it in the issue. Then we can immediatly get
- your issue.
--->
-
-
-I expected to get:
-
-```
-6
-```
-<!--
- Always give your expectations. Each use has their owns.
- You may want daylight saving time to be taken into account,
- someone else want it to be ignored. You may want timezone
- to be used in comparisons, someone else may not, etc.
--->
-
-But I actually get:
-
-```
-5
-```
-<!--
- If you did not succeed to get the same result in
- https://try-carbon.herokuapp.com/ then precise the
- result you get.
--->
-
-Thanks!
+++ /dev/null
-laravel/framework:
- source:
- type: git
- url: https://github.com/laravel/framework.git
- reference: master
- install: composer update --prefer-dist --no-interaction --prefer-stable --no-suggest
+++ /dev/null
-Copyright (C) Brian Nesbitt
-
-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.
+++ /dev/null
-{
- "name": "nesbot/carbon",
- "type": "library",
- "description": "A simple API extension for DateTime.",
- "keywords": [
- "date",
- "time",
- "DateTime"
- ],
- "homepage": "http://carbon.nesbot.com",
- "support": {
- "issues": "https://github.com/briannesbitt/Carbon/issues",
- "source": "https://github.com/briannesbitt/Carbon"
- },
- "license": "MIT",
- "authors": [
- {
- "name": "Brian Nesbitt",
- "email": "brian@nesbot.com",
- "homepage": "http://nesbot.com"
- }
- ],
- "minimum-stability": "dev",
- "require": {
- "php": "^7.1.8 || ^8.0",
- "ext-json": "*",
- "symfony/translation": "^3.4 || ^4.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^2.14 || ^3.0",
- "kylekatarnls/multi-tester": "^1.1",
- "phpmd/phpmd": "^2.6",
- "phpstan/phpstan": "^0.11",
- "phpunit/phpunit": "^7.5 || ^8.0",
- "squizlabs/php_codesniffer": "^3.4"
- },
- "autoload": {
- "psr-4": {
- "Carbon\\": "src/Carbon/"
- }
- },
- "autoload-dev": {
- "psr-4": {
- "Tests\\": "tests/"
- }
- },
- "config": {
- "process-timeout": 0,
- "sort-packages": true
- },
- "scripts": {
- "test": [
- "@phpunit",
- "@phpcs"
- ],
- "phpunit": "phpunit --verbose",
- "phpcs": "php-cs-fixer fix -v --diff --dry-run",
- "phpstan": "phpstan analyse --configuration phpstan.neon --level 3 src tests",
- "phpmd": "phpmd src text /phpmd.xml",
- "phpdoc": "php phpdoc.php"
- },
- "extra": {
- "laravel": {
- "providers": [
- "Carbon\\Laravel\\ServiceProvider"
- ]
- }
- }
-}
+++ /dev/null
-# Contributing to Carbon
-
-## Issue Contributions
-
-Please report any security issue using [Tidelift security contact](https://tidelift.com/security).
-Tidelift will coordinate the fix and disclosure.
-Please don't disclose security bugs publicly until they have been handled by us.
-
-For any other bug or issue, please click this link and follow the template:
-[Create new issue](https://github.com/briannesbitt/Carbon/issues/new)
-
-You may think this template does not apply to your case but please think again. A long description will never be as
-clear as a code chunk with the output you expect from it (for either bug report or new features).
-
-## Code Contributions
-
-### Where to begin
-
-We use the label **good first issue** to tag issues that could be a good fit for new contributors, see if there are such issues now following this link:
-
-https://github.com/briannesbitt/Carbon/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
-
-Else, check the roadmap to see what we plan to do in next releases:
-
-https://github.com/briannesbitt/Carbon/issues/1681
-
-### Develop locally, then submit changes
-
-Fork the [GitHub project](https://github.com/briannesbitt/Carbon) and download it locally:
-
-```shell
-git clone https://github.com/<username>/Carbon.git
-cd Carbon
-git remote add upstream https://github.com/briannesbitt/Carbon.git
-```
-Replace `<username>` with your GitHub username.
-
-Then, you can work on the master or create a specific branch for your development:
-
-```shell
-git checkout -b my-feature-branch -t origin/master
-```
-
-You can now edit the "Carbon" directory contents.
-
-Before committing, please set your name and your e-mail (use the same e-mail address as in your GitHub account):
-
-```shell
-git config --global user.name "Your Name"
-git config --global user.email "your.email.address@example.com"
-```
-
-The ```--global``` argument will apply this setting for all your git repositories, remove it to set only your Carbon
-fork with those settings.
-
-Now you can commit your modifications as you usually do with git:
-
-```shell
-git add --all
-git commit -m "The commit message log"
-```
-
-If your patch fixes an open issue, please insert ```#``` immediately followed by the issue number:
-
-```shell
-git commit -m "#21 Fix this or that"
-```
-
-Use git rebase (not git merge) to sync your work from time to time:
-
-```shell
-git fetch origin
-git rebase origin/master
-```
-
-Please add some tests for bug fixes and features (so it will ensure next developments will not break your code),
-then check all is right with phpunit:
-
-Install PHP if you haven't yet, then install composer:
-https://getcomposer.org/download/
-
-Update dependencies:
-```
-./composer.phar update
-```
-
-Or if you installed composer globally:
-```
-composer update
-```
-
-Then call phpunit:
-```
-./vendor/bin/phpunit
-```
-
-Make sure all tests succeed before submitting your pull-request, else we will not be able to merge it.
-
-Push your work on your remote GitHub fork with:
-```
-git push origin my-feature-branch
-```
-
-Go to https://github.com/yourusername/Carbon and select your feature branch. Click the 'Pull Request' button and fill
-out the form.
-
-We will review it within a few days. And we thank you in advance for your help.
-
-## Versioning
-
-### Note about Semantic Versioning and breaking changes
-
-As a developer, you must understand every change is a breaking change. What is a bug for someone
-is expected in someone else's workflow. The consequence of a change strongly depends on the usage.
-[Semantic Versioning](https://semver.org/) relies to public API. In PHP, the public API of a class is its public
-methods. However, if you extend a class, you can access protected methods, then if you use reflexion, you can
-access private methods. So anything can become a public API if you force it to be. That doesn't mean we should handle
-any possible usage, else we would have to publish a major release for each change and it would no longer make sense.
-
-So before any complain about a breaking change, be warned, we do not guarantee a strict Semantic Versioning as you
-may expect, we're following a pragmatic interpretation of Semantic Versioning that allows the software to evolve in a
-reliable way with reasonable maintenance effort.
-
-Concretely, we consider a change as breaking if it makes fail one of our unit test. We will do our best to avoid
-incompatibilities with libraries that extends Carbon classes (such as Laravel that is continuously tested thanks to
-Travis CI, [see the compatibility matrix](https://github.com/kylekatarnls/carbon-laravel/tree/master#carbon-1-dev-version-1next)).
-
-If you're the owner of a library that strongly depends on Carbon, we recommend you to run unit tests daily requiring
-`"nesbot/carbon": "dev-master"` (for `^2`) or `"nesbot/carbon": "dev-version-1.next"` (for `^1`), this way you can
-detect incompatibilities earlier and report it to us before we tag a release. We'll pay attention and try to fix it to
-make update to next minor releases as soft as possible.
-
-We reserve the right to publish emergency patches within 24 hours after a release if a tag that does not respect
-this pattern would have been released despite our vigilance. In this very rare and particular case, we would mark the
-tag as broken on GitHub and backward compatibility would be based on previous stable tag.
-
-Last, you must understand that Carbon extends PHP natives classes, that means Carbon can be impacted by any change
-that occurs in the date/time API of PHP. We watch new PHP versions and handle those changes as quickly as possible
-when detected, but as PHP does not follow the semantic versioning pattern, it basically means any releases (including
-patches) can have unexpected consequences on Carbon methods results.
-
-### Long term support
-
-To benefit the better support, require Carbon using major version range (`^1` or `^2`). By requiring `1.26.*`,
-`~1.26.0` or limited range such as `>=1.20 <1.33`, you fall to low priority support (only security and critical issues
-will be fixed), our prior support goes to next minor releases of each major version. It applies to bug fixes and
-low-cost features. Other new features will only be added in the last stable release. At the opposite, we recommend you
-to restrain to a major number, as there is no compatibility guarantee from a major version to the next. It means
-requiring `>=2`, as it allows any newer version, will probably leads to errors on releasing our next major version.
-
-Open milestones can be patched if a minor bug is detected while if you're on a closed milestone, we'll more likely
-ask you to update first to an open one. See currently open milestones:
-
-https://github.com/briannesbitt/Carbon/milestones
+++ /dev/null
-<?xml version="1.0"?>
-<ruleset name="Mess detection rules for Carbon"
- 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">
- <description>
- Mess detection rules for Carbon
- </description>
- <rule ref="rulesets/codesize.xml" />
- <rule ref="rulesets/cleancode.xml" />
- <rule ref="rulesets/controversial.xml" />
- <rule ref="rulesets/design.xml" />
- <rule ref="rulesets/naming.xml/ShortVariable">
- <properties>
- <property name="exceptions" value="id,tz" />
- </properties>
- </rule>
- <rule ref="rulesets/unusedcode.xml" />
-</ruleset>
+++ /dev/null
-# Carbon
-
-[](https://packagist.org/packages/nesbot/carbon)
-[](https://packagist.org/packages/nesbot/carbon)
-[](https://travis-ci.org/briannesbitt/Carbon)
-[](https://styleci.io/repos/5724990)
-[](https://codecov.io/github/briannesbitt/Carbon?branch=master)
-[](https://github.com/phpstan/phpstan)
-[](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
-
-An international PHP extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
-
-```php
-use Carbon\Carbon;
-
-printf("Right now is %s", Carbon::now()->toDateTimeString());
-printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString()
-$tomorrow = Carbon::now()->addDay();
-$lastWeek = Carbon::now()->subWeek();
-$nextSummerOlympics = Carbon::createFromDate(2016)->addYears(4);
-
-$officialDate = Carbon::now()->toRfc2822String();
-
-$howOldAmI = Carbon::createFromDate(1975, 5, 21)->age;
-
-$noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London');
-
-$internetWillBlowUpOn = Carbon::create(2038, 01, 19, 3, 14, 7, 'GMT');
-
-// Don't really want this to happen so mock now
-Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1));
-
-// comparisons are always done in UTC
-if (Carbon::now()->gte($internetWillBlowUpOn)) {
- die();
-}
-
-// Phew! Return to normal behaviour
-Carbon::setTestNow();
-
-if (Carbon::now()->isWeekend()) {
- echo 'Party!';
-}
-// Over 200 languages (and over 500 regional variants) supported:
-echo Carbon::now()->subMinutes(2)->diffForHumans(); // '2 minutes ago'
-echo Carbon::now()->subMinutes(2)->locale('zh_CN')->diffForHumans(); // '2分钟前'
-echo Carbon::parse('2019-07-23 14:51')->isoFormat('LLLL'); // 'Tuesday, July 23, 2019 2:51 PM'
-echo Carbon::parse('2019-07-23 14:51')->locale('fr_FR')->isoFormat('LLLL'); // 'mardi 23 juillet 2019 14:51'
-
-// ... but also does 'from now', 'after' and 'before'
-// rolling up to seconds, minutes, hours, days, months, years
-
-$daysSinceEpoch = Carbon::createFromTimestamp(0)->diffInDays();
-```
-
-[Get supported nesbot/carbon with the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
-
-## Installation
-
-### With Composer
-
-```
-$ composer require nesbot/carbon
-```
-
-```json
-{
- "require": {
- "nesbot/carbon": "^2.16"
- }
-}
-```
-
-```php
-<?php
-require 'vendor/autoload.php';
-
-use Carbon\Carbon;
-
-printf("Now: %s", Carbon::now());
-```
-
-<a name="install-nocomposer"/>
-
-### Without Composer
-
-Why are you not using [composer](http://getcomposer.org/)? Download the Carbon [latest release](https://github.com/briannesbitt/Carbon/releases) and put the contents of the ZIP archive into a directory in your project. Then require the file `autoload.php` to get all classes and dependencies loaded on need.
-
-```php
-<?php
-require 'path-to-Carbon-directory/autoload.php';
-
-use Carbon\Carbon;
-
-printf("Now: %s", Carbon::now());
-```
-
-## Docs
-
-[http://carbon.nesbot.com/docs](http://carbon.nesbot.com/docs)
-
-## Security contact information
-
-To report a security vulnerability, please use the
-[Tidelift security contact](https://tidelift.com/security).
-Tidelift will coordinate the fix and disclosure.
-
-## Credits
-
-### Contributors
-
-This project exists thanks to all the people who contribute.
-
-<a href="https://github.com/briannesbitt/Carbon/graphs/contributors" target="_blank"><img src="https://opencollective.com/Carbon/contributors.svg?width=890&button=false" /></a>
-
-### Translators
-
-[Thanks to people helping us to translate Carbon in so many languages](https://carbon.nesbot.com/contribute/translators/)
-
-### Backers
-
-Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Carbon#backer)]
-
-<a href="https://opencollective.com/Carbon#backers" target="_blank"><img src="https://opencollective.com/Carbon/backers.svg?width=890"></a>
-
-### Sponsors
-
-Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Carbon#sponsor)]
-<a href="https://opencollective.com/Carbon/sponsor/0/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/Carbon/sponsor/1/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/Carbon/sponsor/2/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/2/avatar.svg"></a>
-<a href="https://opencollective.com/Carbon/sponsor/3/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/3/avatar.svg"></a>
-<a href="https://opencollective.com/Carbon/sponsor/4/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/4/avatar.svg"></a>
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use Carbon\Traits\Date;
-use DateTime;
-
-/**
- * A simple API extension for DateTime.
- *
- * <autodoc generated by `composer phpdoc`>
- *
- * @property int $year
- * @property int $yearIso
- * @property int $month
- * @property int $day
- * @property int $hour
- * @property int $minute
- * @property int $second
- * @property int $micro
- * @property int $microsecond
- * @property int $timestamp seconds since the Unix Epoch
- * @property string $englishDayOfWeek the day of week in English
- * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
- * @property string $englishMonth the month in English
- * @property string $shortEnglishMonth the abbreviated month in English
- * @property string $localeDayOfWeek the day of week in current locale LC_TIME
- * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
- * @property string $localeMonth the month in current locale LC_TIME
- * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
- * @property int $milliseconds
- * @property int $millisecond
- * @property int $milli
- * @property int $week 1 through 53
- * @property int $isoWeek 1 through 53
- * @property int $weekYear year according to week format
- * @property int $isoWeekYear year according to ISO week format
- * @property int $dayOfYear 1 through 366
- * @property int $age does a diffInYears() with default parameters
- * @property int $offset the timezone offset in seconds from UTC
- * @property int $offsetMinutes the timezone offset in minutes from UTC
- * @property int $offsetHours the timezone offset in hours from UTC
- * @property CarbonTimeZone $timezone the current timezone
- * @property CarbonTimeZone $tz alias of $timezone
- * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
- * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
- * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
- * @property-read int $daysInMonth number of days in the given month
- * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
- * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
- * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read int $noZeroHour current hour from 1 to 24
- * @property-read int $weeksInYear 51 through 53
- * @property-read int $isoWeeksInYear 51 through 53
- * @property-read int $weekOfMonth 1 through 5
- * @property-read int $weekNumberInMonth 1 through 5
- * @property-read int $firstWeekDay 0 through 6
- * @property-read int $lastWeekDay 0 through 6
- * @property-read int $daysInYear 365 or 366
- * @property-read int $quarter the quarter of this instance, 1 - 4
- * @property-read int $decade the decade of this instance
- * @property-read int $century the century of this instance
- * @property-read int $millennium the millennium of this instance
- * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
- * @property-read bool $local checks if the timezone is local, true if local, false otherwise
- * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
- * @property-read string $timezoneName the current timezone name
- * @property-read string $tzName alias of $timezoneName
- * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
- * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
- * @property-read string $locale locale of the current instance
- *
- * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
- * @method bool isLocal() Check if the current instance has non-UTC timezone.
- * @method bool isValid() Check if the current instance is a valid date.
- * @method bool isDST() Check if the current instance is in a daylight saving time.
- * @method bool isSunday() Checks if the instance day is sunday.
- * @method bool isMonday() Checks if the instance day is monday.
- * @method bool isTuesday() Checks if the instance day is tuesday.
- * @method bool isWednesday() Checks if the instance day is wednesday.
- * @method bool isThursday() Checks if the instance day is thursday.
- * @method bool isFriday() Checks if the instance day is friday.
- * @method bool isSaturday() Checks if the instance day is saturday.
- * @method bool isSameYear(\DateTimeInterface $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
- * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
- * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
- * @method bool isSameWeek(\DateTimeInterface $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
- * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
- * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
- * @method bool isSameDay(\DateTimeInterface $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
- * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
- * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
- * @method bool isSameHour(\DateTimeInterface $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
- * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
- * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
- * @method bool isSameMinute(\DateTimeInterface $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
- * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
- * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
- * @method bool isSameSecond(\DateTimeInterface $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
- * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
- * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
- * @method bool isSameMicro(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isSameMicrosecond(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
- * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
- * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
- * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
- * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
- * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
- * @method bool isSameDecade(\DateTimeInterface $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
- * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
- * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
- * @method bool isSameCentury(\DateTimeInterface $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
- * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
- * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
- * @method bool isSameMillennium(\DateTimeInterface $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
- * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
- * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
- * @method $this years(int $value) Set current instance year to the given value.
- * @method $this year(int $value) Set current instance year to the given value.
- * @method $this setYears(int $value) Set current instance year to the given value.
- * @method $this setYear(int $value) Set current instance year to the given value.
- * @method $this months(int $value) Set current instance month to the given value.
- * @method $this month(int $value) Set current instance month to the given value.
- * @method $this setMonths(int $value) Set current instance month to the given value.
- * @method $this setMonth(int $value) Set current instance month to the given value.
- * @method $this days(int $value) Set current instance day to the given value.
- * @method $this day(int $value) Set current instance day to the given value.
- * @method $this setDays(int $value) Set current instance day to the given value.
- * @method $this setDay(int $value) Set current instance day to the given value.
- * @method $this hours(int $value) Set current instance hour to the given value.
- * @method $this hour(int $value) Set current instance hour to the given value.
- * @method $this setHours(int $value) Set current instance hour to the given value.
- * @method $this setHour(int $value) Set current instance hour to the given value.
- * @method $this minutes(int $value) Set current instance minute to the given value.
- * @method $this minute(int $value) Set current instance minute to the given value.
- * @method $this setMinutes(int $value) Set current instance minute to the given value.
- * @method $this setMinute(int $value) Set current instance minute to the given value.
- * @method $this seconds(int $value) Set current instance second to the given value.
- * @method $this second(int $value) Set current instance second to the given value.
- * @method $this setSeconds(int $value) Set current instance second to the given value.
- * @method $this setSecond(int $value) Set current instance second to the given value.
- * @method $this millis(int $value) Set current instance millisecond to the given value.
- * @method $this milli(int $value) Set current instance millisecond to the given value.
- * @method $this setMillis(int $value) Set current instance millisecond to the given value.
- * @method $this setMilli(int $value) Set current instance millisecond to the given value.
- * @method $this milliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this millisecond(int $value) Set current instance millisecond to the given value.
- * @method $this setMilliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this setMillisecond(int $value) Set current instance millisecond to the given value.
- * @method $this micros(int $value) Set current instance microsecond to the given value.
- * @method $this micro(int $value) Set current instance microsecond to the given value.
- * @method $this setMicros(int $value) Set current instance microsecond to the given value.
- * @method $this setMicro(int $value) Set current instance microsecond to the given value.
- * @method $this microseconds(int $value) Set current instance microsecond to the given value.
- * @method $this microsecond(int $value) Set current instance microsecond to the given value.
- * @method $this setMicroseconds(int $value) Set current instance microsecond to the given value.
- * @method $this setMicrosecond(int $value) Set current instance microsecond to the given value.
- * @method $this addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
- * @method $this addYear() Add one year to the instance (using date interval).
- * @method $this subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
- * @method $this subYear() Sub one year to the instance (using date interval).
- * @method $this addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
- * @method $this addMonth() Add one month to the instance (using date interval).
- * @method $this subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
- * @method $this subMonth() Sub one month to the instance (using date interval).
- * @method $this addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
- * @method $this addDay() Add one day to the instance (using date interval).
- * @method $this subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
- * @method $this subDay() Sub one day to the instance (using date interval).
- * @method $this addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
- * @method $this addHour() Add one hour to the instance (using date interval).
- * @method $this subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
- * @method $this subHour() Sub one hour to the instance (using date interval).
- * @method $this addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
- * @method $this addMinute() Add one minute to the instance (using date interval).
- * @method $this subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
- * @method $this subMinute() Sub one minute to the instance (using date interval).
- * @method $this addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
- * @method $this addSecond() Add one second to the instance (using date interval).
- * @method $this subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
- * @method $this subSecond() Sub one second to the instance (using date interval).
- * @method $this addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMilli() Add one millisecond to the instance (using date interval).
- * @method $this subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMilli() Sub one millisecond to the instance (using date interval).
- * @method $this addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMillisecond() Add one millisecond to the instance (using date interval).
- * @method $this subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMillisecond() Sub one millisecond to the instance (using date interval).
- * @method $this addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicro() Add one microsecond to the instance (using date interval).
- * @method $this subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicro() Sub one microsecond to the instance (using date interval).
- * @method $this addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicrosecond() Add one microsecond to the instance (using date interval).
- * @method $this subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicrosecond() Sub one microsecond to the instance (using date interval).
- * @method $this addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
- * @method $this addMillennium() Add one millennium to the instance (using date interval).
- * @method $this subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
- * @method $this subMillennium() Sub one millennium to the instance (using date interval).
- * @method $this addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
- * @method $this addCentury() Add one century to the instance (using date interval).
- * @method $this subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
- * @method $this subCentury() Sub one century to the instance (using date interval).
- * @method $this addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
- * @method $this addDecade() Add one decade to the instance (using date interval).
- * @method $this subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
- * @method $this subDecade() Sub one decade to the instance (using date interval).
- * @method $this addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
- * @method $this addQuarter() Add one quarter to the instance (using date interval).
- * @method $this subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
- * @method $this subQuarter() Sub one quarter to the instance (using date interval).
- * @method $this addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
- * @method $this addWeek() Add one week to the instance (using date interval).
- * @method $this subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
- * @method $this subWeek() Sub one week to the instance (using date interval).
- * @method $this addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this addWeekday() Add one weekday to the instance (using date interval).
- * @method $this subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this subWeekday() Sub one weekday to the instance (using date interval).
- * @method $this addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicro() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicro() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicrosecond() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMilli() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMilli() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillisecond() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillisecond() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealSecond() Add one second to the instance (using timestamp).
- * @method $this subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealSecond() Sub one second to the instance (using timestamp).
- * @method $this addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMinute() Add one minute to the instance (using timestamp).
- * @method $this subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMinute() Sub one minute to the instance (using timestamp).
- * @method $this addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealHour() Add one hour to the instance (using timestamp).
- * @method $this subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealHour() Sub one hour to the instance (using timestamp).
- * @method $this addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDay() Add one day to the instance (using timestamp).
- * @method $this subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDay() Sub one day to the instance (using timestamp).
- * @method $this addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealWeek() Add one week to the instance (using timestamp).
- * @method $this subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealWeek() Sub one week to the instance (using timestamp).
- * @method $this addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMonth() Add one month to the instance (using timestamp).
- * @method $this subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMonth() Sub one month to the instance (using timestamp).
- * @method $this addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealQuarter() Add one quarter to the instance (using timestamp).
- * @method $this subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealQuarter() Sub one quarter to the instance (using timestamp).
- * @method $this addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealYear() Add one year to the instance (using timestamp).
- * @method $this subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealYear() Sub one year to the instance (using timestamp).
- * @method $this addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDecade() Add one decade to the instance (using timestamp).
- * @method $this subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDecade() Sub one decade to the instance (using timestamp).
- * @method $this addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealCentury() Add one century to the instance (using timestamp).
- * @method $this subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealCentury() Sub one century to the instance (using timestamp).
- * @method $this addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillennium() Add one millennium to the instance (using timestamp).
- * @method $this subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillennium() Sub one millennium to the instance (using timestamp).
- * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method string shortAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- *
- * </autodoc>
- */
-class Carbon extends DateTime implements CarbonInterface
-{
- use Date;
-
- public static function isMutable()
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use Carbon\Traits\Date;
-use DateTimeImmutable;
-
-/**
- * A simple API extension for DateTimeImmutable.
- *
- * <autodoc generated by `composer phpdoc`>
- *
- * @property int $year
- * @property int $yearIso
- * @property int $month
- * @property int $day
- * @property int $hour
- * @property int $minute
- * @property int $second
- * @property int $micro
- * @property int $microsecond
- * @property int $timestamp seconds since the Unix Epoch
- * @property string $englishDayOfWeek the day of week in English
- * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
- * @property string $englishMonth the month in English
- * @property string $shortEnglishMonth the abbreviated month in English
- * @property string $localeDayOfWeek the day of week in current locale LC_TIME
- * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
- * @property string $localeMonth the month in current locale LC_TIME
- * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
- * @property int $milliseconds
- * @property int $millisecond
- * @property int $milli
- * @property int $week 1 through 53
- * @property int $isoWeek 1 through 53
- * @property int $weekYear year according to week format
- * @property int $isoWeekYear year according to ISO week format
- * @property int $dayOfYear 1 through 366
- * @property int $age does a diffInYears() with default parameters
- * @property int $offset the timezone offset in seconds from UTC
- * @property int $offsetMinutes the timezone offset in minutes from UTC
- * @property int $offsetHours the timezone offset in hours from UTC
- * @property CarbonTimeZone $timezone the current timezone
- * @property CarbonTimeZone $tz alias of $timezone
- * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
- * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
- * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
- * @property-read int $daysInMonth number of days in the given month
- * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
- * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
- * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read int $noZeroHour current hour from 1 to 24
- * @property-read int $weeksInYear 51 through 53
- * @property-read int $isoWeeksInYear 51 through 53
- * @property-read int $weekOfMonth 1 through 5
- * @property-read int $weekNumberInMonth 1 through 5
- * @property-read int $firstWeekDay 0 through 6
- * @property-read int $lastWeekDay 0 through 6
- * @property-read int $daysInYear 365 or 366
- * @property-read int $quarter the quarter of this instance, 1 - 4
- * @property-read int $decade the decade of this instance
- * @property-read int $century the century of this instance
- * @property-read int $millennium the millennium of this instance
- * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
- * @property-read bool $local checks if the timezone is local, true if local, false otherwise
- * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
- * @property-read string $timezoneName the current timezone name
- * @property-read string $tzName alias of $timezoneName
- * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
- * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
- * @property-read string $locale locale of the current instance
- *
- * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
- * @method bool isLocal() Check if the current instance has non-UTC timezone.
- * @method bool isValid() Check if the current instance is a valid date.
- * @method bool isDST() Check if the current instance is in a daylight saving time.
- * @method bool isSunday() Checks if the instance day is sunday.
- * @method bool isMonday() Checks if the instance day is monday.
- * @method bool isTuesday() Checks if the instance day is tuesday.
- * @method bool isWednesday() Checks if the instance day is wednesday.
- * @method bool isThursday() Checks if the instance day is thursday.
- * @method bool isFriday() Checks if the instance day is friday.
- * @method bool isSaturday() Checks if the instance day is saturday.
- * @method bool isSameYear(\DateTimeInterface $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
- * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
- * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
- * @method bool isSameWeek(\DateTimeInterface $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
- * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
- * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
- * @method bool isSameDay(\DateTimeInterface $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
- * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
- * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
- * @method bool isSameHour(\DateTimeInterface $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
- * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
- * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
- * @method bool isSameMinute(\DateTimeInterface $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
- * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
- * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
- * @method bool isSameSecond(\DateTimeInterface $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
- * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
- * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
- * @method bool isSameMicro(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isSameMicrosecond(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
- * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
- * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
- * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
- * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
- * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
- * @method bool isSameDecade(\DateTimeInterface $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
- * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
- * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
- * @method bool isSameCentury(\DateTimeInterface $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
- * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
- * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
- * @method bool isSameMillennium(\DateTimeInterface $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
- * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
- * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
- * @method $this years(int $value) Set current instance year to the given value.
- * @method $this year(int $value) Set current instance year to the given value.
- * @method $this setYears(int $value) Set current instance year to the given value.
- * @method $this setYear(int $value) Set current instance year to the given value.
- * @method $this months(int $value) Set current instance month to the given value.
- * @method $this month(int $value) Set current instance month to the given value.
- * @method $this setMonths(int $value) Set current instance month to the given value.
- * @method $this setMonth(int $value) Set current instance month to the given value.
- * @method $this days(int $value) Set current instance day to the given value.
- * @method $this day(int $value) Set current instance day to the given value.
- * @method $this setDays(int $value) Set current instance day to the given value.
- * @method $this setDay(int $value) Set current instance day to the given value.
- * @method $this hours(int $value) Set current instance hour to the given value.
- * @method $this hour(int $value) Set current instance hour to the given value.
- * @method $this setHours(int $value) Set current instance hour to the given value.
- * @method $this setHour(int $value) Set current instance hour to the given value.
- * @method $this minutes(int $value) Set current instance minute to the given value.
- * @method $this minute(int $value) Set current instance minute to the given value.
- * @method $this setMinutes(int $value) Set current instance minute to the given value.
- * @method $this setMinute(int $value) Set current instance minute to the given value.
- * @method $this seconds(int $value) Set current instance second to the given value.
- * @method $this second(int $value) Set current instance second to the given value.
- * @method $this setSeconds(int $value) Set current instance second to the given value.
- * @method $this setSecond(int $value) Set current instance second to the given value.
- * @method $this millis(int $value) Set current instance millisecond to the given value.
- * @method $this milli(int $value) Set current instance millisecond to the given value.
- * @method $this setMillis(int $value) Set current instance millisecond to the given value.
- * @method $this setMilli(int $value) Set current instance millisecond to the given value.
- * @method $this milliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this millisecond(int $value) Set current instance millisecond to the given value.
- * @method $this setMilliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this setMillisecond(int $value) Set current instance millisecond to the given value.
- * @method $this micros(int $value) Set current instance microsecond to the given value.
- * @method $this micro(int $value) Set current instance microsecond to the given value.
- * @method $this setMicros(int $value) Set current instance microsecond to the given value.
- * @method $this setMicro(int $value) Set current instance microsecond to the given value.
- * @method $this microseconds(int $value) Set current instance microsecond to the given value.
- * @method $this microsecond(int $value) Set current instance microsecond to the given value.
- * @method $this setMicroseconds(int $value) Set current instance microsecond to the given value.
- * @method $this setMicrosecond(int $value) Set current instance microsecond to the given value.
- * @method $this addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
- * @method $this addYear() Add one year to the instance (using date interval).
- * @method $this subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
- * @method $this subYear() Sub one year to the instance (using date interval).
- * @method $this addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
- * @method $this addMonth() Add one month to the instance (using date interval).
- * @method $this subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
- * @method $this subMonth() Sub one month to the instance (using date interval).
- * @method $this addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
- * @method $this addDay() Add one day to the instance (using date interval).
- * @method $this subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
- * @method $this subDay() Sub one day to the instance (using date interval).
- * @method $this addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
- * @method $this addHour() Add one hour to the instance (using date interval).
- * @method $this subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
- * @method $this subHour() Sub one hour to the instance (using date interval).
- * @method $this addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
- * @method $this addMinute() Add one minute to the instance (using date interval).
- * @method $this subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
- * @method $this subMinute() Sub one minute to the instance (using date interval).
- * @method $this addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
- * @method $this addSecond() Add one second to the instance (using date interval).
- * @method $this subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
- * @method $this subSecond() Sub one second to the instance (using date interval).
- * @method $this addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMilli() Add one millisecond to the instance (using date interval).
- * @method $this subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMilli() Sub one millisecond to the instance (using date interval).
- * @method $this addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMillisecond() Add one millisecond to the instance (using date interval).
- * @method $this subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMillisecond() Sub one millisecond to the instance (using date interval).
- * @method $this addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicro() Add one microsecond to the instance (using date interval).
- * @method $this subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicro() Sub one microsecond to the instance (using date interval).
- * @method $this addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicrosecond() Add one microsecond to the instance (using date interval).
- * @method $this subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicrosecond() Sub one microsecond to the instance (using date interval).
- * @method $this addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
- * @method $this addMillennium() Add one millennium to the instance (using date interval).
- * @method $this subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
- * @method $this subMillennium() Sub one millennium to the instance (using date interval).
- * @method $this addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
- * @method $this addCentury() Add one century to the instance (using date interval).
- * @method $this subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
- * @method $this subCentury() Sub one century to the instance (using date interval).
- * @method $this addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
- * @method $this addDecade() Add one decade to the instance (using date interval).
- * @method $this subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
- * @method $this subDecade() Sub one decade to the instance (using date interval).
- * @method $this addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
- * @method $this addQuarter() Add one quarter to the instance (using date interval).
- * @method $this subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
- * @method $this subQuarter() Sub one quarter to the instance (using date interval).
- * @method $this addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
- * @method $this addWeek() Add one week to the instance (using date interval).
- * @method $this subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
- * @method $this subWeek() Sub one week to the instance (using date interval).
- * @method $this addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this addWeekday() Add one weekday to the instance (using date interval).
- * @method $this subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this subWeekday() Sub one weekday to the instance (using date interval).
- * @method $this addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicro() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicro() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicrosecond() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMilli() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMilli() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillisecond() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillisecond() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealSecond() Add one second to the instance (using timestamp).
- * @method $this subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealSecond() Sub one second to the instance (using timestamp).
- * @method $this addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMinute() Add one minute to the instance (using timestamp).
- * @method $this subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMinute() Sub one minute to the instance (using timestamp).
- * @method $this addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealHour() Add one hour to the instance (using timestamp).
- * @method $this subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealHour() Sub one hour to the instance (using timestamp).
- * @method $this addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDay() Add one day to the instance (using timestamp).
- * @method $this subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDay() Sub one day to the instance (using timestamp).
- * @method $this addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealWeek() Add one week to the instance (using timestamp).
- * @method $this subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealWeek() Sub one week to the instance (using timestamp).
- * @method $this addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMonth() Add one month to the instance (using timestamp).
- * @method $this subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMonth() Sub one month to the instance (using timestamp).
- * @method $this addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealQuarter() Add one quarter to the instance (using timestamp).
- * @method $this subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealQuarter() Sub one quarter to the instance (using timestamp).
- * @method $this addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealYear() Add one year to the instance (using timestamp).
- * @method $this subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealYear() Sub one year to the instance (using timestamp).
- * @method $this addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDecade() Add one decade to the instance (using timestamp).
- * @method $this subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDecade() Sub one decade to the instance (using timestamp).
- * @method $this addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealCentury() Add one century to the instance (using timestamp).
- * @method $this subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealCentury() Sub one century to the instance (using timestamp).
- * @method $this addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillennium() Add one millennium to the instance (using timestamp).
- * @method $this subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillennium() Sub one millennium to the instance (using timestamp).
- * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method string shortAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- *
- * </autodoc>
- */
-class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
-{
- use Date;
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use Closure;
-use DateInterval;
-use DateTime;
-use DateTimeInterface;
-use InvalidArgumentException;
-use JsonSerializable;
-use ReflectionException;
-
-/**
- * Common interface for Carbon and CarbonImmutable.
- *
- * <autodoc generated by `composer phpdoc`>
- *
- * @property int $year
- * @property int $yearIso
- * @property int $month
- * @property int $day
- * @property int $hour
- * @property int $minute
- * @property int $second
- * @property int $micro
- * @property int $microsecond
- * @property int $timestamp seconds since the Unix Epoch
- * @property string $englishDayOfWeek the day of week in English
- * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
- * @property string $englishMonth the month in English
- * @property string $shortEnglishMonth the abbreviated month in English
- * @property string $localeDayOfWeek the day of week in current locale LC_TIME
- * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
- * @property string $localeMonth the month in current locale LC_TIME
- * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
- * @property int $milliseconds
- * @property int $millisecond
- * @property int $milli
- * @property int $week 1 through 53
- * @property int $isoWeek 1 through 53
- * @property int $weekYear year according to week format
- * @property int $isoWeekYear year according to ISO week format
- * @property int $dayOfYear 1 through 366
- * @property int $age does a diffInYears() with default parameters
- * @property int $offset the timezone offset in seconds from UTC
- * @property int $offsetMinutes the timezone offset in minutes from UTC
- * @property int $offsetHours the timezone offset in hours from UTC
- * @property CarbonTimeZone $timezone the current timezone
- * @property CarbonTimeZone $tz alias of $timezone
- * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
- * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
- * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
- * @property-read int $daysInMonth number of days in the given month
- * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
- * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
- * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read int $noZeroHour current hour from 1 to 24
- * @property-read int $weeksInYear 51 through 53
- * @property-read int $isoWeeksInYear 51 through 53
- * @property-read int $weekOfMonth 1 through 5
- * @property-read int $weekNumberInMonth 1 through 5
- * @property-read int $firstWeekDay 0 through 6
- * @property-read int $lastWeekDay 0 through 6
- * @property-read int $daysInYear 365 or 366
- * @property-read int $quarter the quarter of this instance, 1 - 4
- * @property-read int $decade the decade of this instance
- * @property-read int $century the century of this instance
- * @property-read int $millennium the millennium of this instance
- * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
- * @property-read bool $local checks if the timezone is local, true if local, false otherwise
- * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
- * @property-read string $timezoneName the current timezone name
- * @property-read string $tzName alias of $timezoneName
- * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
- * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
- * @property-read string $locale locale of the current instance
- *
- * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
- * @method bool isLocal() Check if the current instance has non-UTC timezone.
- * @method bool isValid() Check if the current instance is a valid date.
- * @method bool isDST() Check if the current instance is in a daylight saving time.
- * @method bool isSunday() Checks if the instance day is sunday.
- * @method bool isMonday() Checks if the instance day is monday.
- * @method bool isTuesday() Checks if the instance day is tuesday.
- * @method bool isWednesday() Checks if the instance day is wednesday.
- * @method bool isThursday() Checks if the instance day is thursday.
- * @method bool isFriday() Checks if the instance day is friday.
- * @method bool isSaturday() Checks if the instance day is saturday.
- * @method bool isSameYear(\DateTimeInterface $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
- * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
- * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
- * @method bool isSameWeek(\DateTimeInterface $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
- * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
- * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
- * @method bool isSameDay(\DateTimeInterface $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
- * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
- * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
- * @method bool isSameHour(\DateTimeInterface $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
- * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
- * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
- * @method bool isSameMinute(\DateTimeInterface $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
- * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
- * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
- * @method bool isSameSecond(\DateTimeInterface $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
- * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
- * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
- * @method bool isSameMicro(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isSameMicrosecond(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
- * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
- * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
- * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
- * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
- * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
- * @method bool isSameDecade(\DateTimeInterface $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
- * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
- * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
- * @method bool isSameCentury(\DateTimeInterface $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
- * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
- * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
- * @method bool isSameMillennium(\DateTimeInterface $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
- * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
- * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
- * @method $this years(int $value) Set current instance year to the given value.
- * @method $this year(int $value) Set current instance year to the given value.
- * @method $this setYears(int $value) Set current instance year to the given value.
- * @method $this setYear(int $value) Set current instance year to the given value.
- * @method $this months(int $value) Set current instance month to the given value.
- * @method $this month(int $value) Set current instance month to the given value.
- * @method $this setMonths(int $value) Set current instance month to the given value.
- * @method $this setMonth(int $value) Set current instance month to the given value.
- * @method $this days(int $value) Set current instance day to the given value.
- * @method $this day(int $value) Set current instance day to the given value.
- * @method $this setDays(int $value) Set current instance day to the given value.
- * @method $this setDay(int $value) Set current instance day to the given value.
- * @method $this hours(int $value) Set current instance hour to the given value.
- * @method $this hour(int $value) Set current instance hour to the given value.
- * @method $this setHours(int $value) Set current instance hour to the given value.
- * @method $this setHour(int $value) Set current instance hour to the given value.
- * @method $this minutes(int $value) Set current instance minute to the given value.
- * @method $this minute(int $value) Set current instance minute to the given value.
- * @method $this setMinutes(int $value) Set current instance minute to the given value.
- * @method $this setMinute(int $value) Set current instance minute to the given value.
- * @method $this seconds(int $value) Set current instance second to the given value.
- * @method $this second(int $value) Set current instance second to the given value.
- * @method $this setSeconds(int $value) Set current instance second to the given value.
- * @method $this setSecond(int $value) Set current instance second to the given value.
- * @method $this millis(int $value) Set current instance millisecond to the given value.
- * @method $this milli(int $value) Set current instance millisecond to the given value.
- * @method $this setMillis(int $value) Set current instance millisecond to the given value.
- * @method $this setMilli(int $value) Set current instance millisecond to the given value.
- * @method $this milliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this millisecond(int $value) Set current instance millisecond to the given value.
- * @method $this setMilliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this setMillisecond(int $value) Set current instance millisecond to the given value.
- * @method $this micros(int $value) Set current instance microsecond to the given value.
- * @method $this micro(int $value) Set current instance microsecond to the given value.
- * @method $this setMicros(int $value) Set current instance microsecond to the given value.
- * @method $this setMicro(int $value) Set current instance microsecond to the given value.
- * @method $this microseconds(int $value) Set current instance microsecond to the given value.
- * @method $this microsecond(int $value) Set current instance microsecond to the given value.
- * @method $this setMicroseconds(int $value) Set current instance microsecond to the given value.
- * @method $this setMicrosecond(int $value) Set current instance microsecond to the given value.
- * @method $this addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
- * @method $this addYear() Add one year to the instance (using date interval).
- * @method $this subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
- * @method $this subYear() Sub one year to the instance (using date interval).
- * @method $this addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
- * @method $this addMonth() Add one month to the instance (using date interval).
- * @method $this subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
- * @method $this subMonth() Sub one month to the instance (using date interval).
- * @method $this addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
- * @method $this addDay() Add one day to the instance (using date interval).
- * @method $this subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
- * @method $this subDay() Sub one day to the instance (using date interval).
- * @method $this addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
- * @method $this addHour() Add one hour to the instance (using date interval).
- * @method $this subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
- * @method $this subHour() Sub one hour to the instance (using date interval).
- * @method $this addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
- * @method $this addMinute() Add one minute to the instance (using date interval).
- * @method $this subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
- * @method $this subMinute() Sub one minute to the instance (using date interval).
- * @method $this addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
- * @method $this addSecond() Add one second to the instance (using date interval).
- * @method $this subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
- * @method $this subSecond() Sub one second to the instance (using date interval).
- * @method $this addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMilli() Add one millisecond to the instance (using date interval).
- * @method $this subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMilli() Sub one millisecond to the instance (using date interval).
- * @method $this addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMillisecond() Add one millisecond to the instance (using date interval).
- * @method $this subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMillisecond() Sub one millisecond to the instance (using date interval).
- * @method $this addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicro() Add one microsecond to the instance (using date interval).
- * @method $this subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicro() Sub one microsecond to the instance (using date interval).
- * @method $this addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicrosecond() Add one microsecond to the instance (using date interval).
- * @method $this subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicrosecond() Sub one microsecond to the instance (using date interval).
- * @method $this addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
- * @method $this addMillennium() Add one millennium to the instance (using date interval).
- * @method $this subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
- * @method $this subMillennium() Sub one millennium to the instance (using date interval).
- * @method $this addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
- * @method $this addCentury() Add one century to the instance (using date interval).
- * @method $this subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
- * @method $this subCentury() Sub one century to the instance (using date interval).
- * @method $this addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
- * @method $this addDecade() Add one decade to the instance (using date interval).
- * @method $this subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
- * @method $this subDecade() Sub one decade to the instance (using date interval).
- * @method $this addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
- * @method $this addQuarter() Add one quarter to the instance (using date interval).
- * @method $this subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
- * @method $this subQuarter() Sub one quarter to the instance (using date interval).
- * @method $this addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
- * @method $this addWeek() Add one week to the instance (using date interval).
- * @method $this subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
- * @method $this subWeek() Sub one week to the instance (using date interval).
- * @method $this addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this addWeekday() Add one weekday to the instance (using date interval).
- * @method $this subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this subWeekday() Sub one weekday to the instance (using date interval).
- * @method $this addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicro() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicro() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicrosecond() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMilli() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMilli() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillisecond() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillisecond() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealSecond() Add one second to the instance (using timestamp).
- * @method $this subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealSecond() Sub one second to the instance (using timestamp).
- * @method $this addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMinute() Add one minute to the instance (using timestamp).
- * @method $this subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMinute() Sub one minute to the instance (using timestamp).
- * @method $this addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealHour() Add one hour to the instance (using timestamp).
- * @method $this subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealHour() Sub one hour to the instance (using timestamp).
- * @method $this addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDay() Add one day to the instance (using timestamp).
- * @method $this subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDay() Sub one day to the instance (using timestamp).
- * @method $this addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealWeek() Add one week to the instance (using timestamp).
- * @method $this subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealWeek() Sub one week to the instance (using timestamp).
- * @method $this addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMonth() Add one month to the instance (using timestamp).
- * @method $this subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMonth() Sub one month to the instance (using timestamp).
- * @method $this addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealQuarter() Add one quarter to the instance (using timestamp).
- * @method $this subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealQuarter() Sub one quarter to the instance (using timestamp).
- * @method $this addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealYear() Add one year to the instance (using timestamp).
- * @method $this subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealYear() Sub one year to the instance (using timestamp).
- * @method $this addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDecade() Add one decade to the instance (using timestamp).
- * @method $this subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDecade() Sub one decade to the instance (using timestamp).
- * @method $this addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealCentury() Add one century to the instance (using timestamp).
- * @method $this subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealCentury() Sub one century to the instance (using timestamp).
- * @method $this addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillennium() Add one millennium to the instance (using timestamp).
- * @method $this subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillennium() Sub one millennium to the instance (using timestamp).
- * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method string shortAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- *
- * </autodoc>
- */
-interface CarbonInterface extends DateTimeInterface, JsonSerializable
-{
- /**
- * Diff wording options(expressed in octal).
- */
- public const NO_ZERO_DIFF = 01;
- public const JUST_NOW = 02;
- public const ONE_DAY_WORDS = 04;
- public const TWO_DAY_WORDS = 010;
- public const SEQUENTIAL_PARTS_ONLY = 020;
-
- /**
- * Diff syntax options.
- */
- public const DIFF_ABSOLUTE = 1; // backward compatibility with true
- public const DIFF_RELATIVE_AUTO = 0; // backward compatibility with false
- public const DIFF_RELATIVE_TO_NOW = 2;
- public const DIFF_RELATIVE_TO_OTHER = 3;
-
- /**
- * Translate string options.
- */
- public const TRANSLATE_MONTHS = 1;
- public const TRANSLATE_DAYS = 2;
- public const TRANSLATE_UNITS = 4;
- public const TRANSLATE_MERIDIEM = 8;
- public const TRANSLATE_ALL = self::TRANSLATE_MONTHS | self::TRANSLATE_DAYS | self::TRANSLATE_UNITS | self::TRANSLATE_MERIDIEM;
-
- /**
- * The day constants.
- */
- public const SUNDAY = 0;
- public const MONDAY = 1;
- public const TUESDAY = 2;
- public const WEDNESDAY = 3;
- public const THURSDAY = 4;
- public const FRIDAY = 5;
- public const SATURDAY = 6;
-
- /**
- * Number of X in Y.
- */
- public const YEARS_PER_MILLENNIUM = 1000;
- public const YEARS_PER_CENTURY = 100;
- public const YEARS_PER_DECADE = 10;
- public const MONTHS_PER_YEAR = 12;
- public const MONTHS_PER_QUARTER = 3;
- public const WEEKS_PER_YEAR = 52;
- public const WEEKS_PER_MONTH = 4;
- public const DAYS_PER_WEEK = 7;
- public const HOURS_PER_DAY = 24;
- public const MINUTES_PER_HOUR = 60;
- public const SECONDS_PER_MINUTE = 60;
- public const MILLISECONDS_PER_SECOND = 1000;
- public const MICROSECONDS_PER_MILLISECOND = 1000;
- public const MICROSECONDS_PER_SECOND = 1000000;
-
- /**
- * RFC7231 DateTime format.
- *
- * @var string
- */
- public const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T';
-
- /**
- * Default format to use for __toString method when type juggling occurs.
- *
- * @var string
- */
- public const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s';
-
- /**
- * Format for converting mocked time, includes microseconds.
- *
- * @var string
- */
- public const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u';
-
- /**
- * Pattern detection for ->isoFormat and ::createFromIsoFormat.
- *
- * @var string
- */
- public const ISO_FORMAT_REGEXP = '(O[YMDHhms]|[Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY?|g{1,5}|G{1,5}|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?)';
-
- // <methods>
-
- /**
- * Dynamically handle calls to the class.
- *
- * @param string $method magic method name called
- * @param array $parameters parameters list
- *
- * @throws \BadMethodCallException|\ReflectionException
- *
- * @return mixed
- */
- public function __call($method, $parameters);
-
- /**
- * Dynamically handle calls to the class.
- *
- * @param string $method magic method name called
- * @param array $parameters parameters list
- *
- * @throws \BadMethodCallException
- *
- * @return mixed
- */
- public static function __callStatic($method, $parameters);
-
- /**
- * Create a new Carbon instance.
- *
- * Please see the testing aids section (specifically static::setTestNow())
- * for more on the possibility of this constructor returning a test instance.
- *
- * @param string|null $time
- * @param \DateTimeZone|string|null $tz
- */
- public function __construct($time = null, $tz = null);
-
- /**
- * Show truthy properties on var_dump().
- *
- * @return array
- */
- public function __debugInfo();
-
- /**
- * Get a part of the Carbon object
- *
- * @param string $name
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return string|int|bool|\DateTimeZone|null
- */
- public function __get($name);
-
- /**
- * Check if an attribute exists on the object
- *
- * @param string $name
- *
- * @return bool
- */
- public function __isset($name);
-
- /**
- * Set a part of the Carbon object
- *
- * @param string $name
- * @param string|int|\DateTimeZone $value
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return void
- */
- public function __set($name, $value);
-
- /**
- * The __set_state handler.
- *
- * @param string|array $dump
- *
- * @return static|CarbonInterface
- */
- public static function __set_state($dump);
-
- /**
- * Returns the list of properties to dump on serialize() called on.
- *
- * @return array
- */
- public function __sleep();
-
- /**
- * Format the instance as a string using the set format
- *
- * @example
- * ```
- * echo Carbon::now(); // Carbon instances can be casted to string
- * ```
- *
- * @return string
- */
- public function __toString();
-
- /**
- * Add given units or interval to the current instance.
- *
- * @example $date->add('hour', 3)
- * @example $date->add(15, 'days')
- * @example $date->add(CarbonInterval::days(4))
- *
- * @param string|DateInterval $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function add($unit, $value = 1, $overflow = null);
-
- /**
- * Add seconds to the instance using timestamp. Positive $value travels
- * forward while negative $value travels into the past.
- *
- * @param string $unit
- * @param int $value
- *
- * @return static
- */
- public function addRealUnit($unit, $value = 1);
-
- /**
- * Add given units to the current instance.
- *
- * @param string $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function addUnit($unit, $value = 1, $overflow = null);
-
- /**
- * Add any unit to a new value without overflowing current other unit given.
- *
- * @param string $valueUnit unit name to modify
- * @param int $value amount to add to the input unit
- * @param string $overflowUnit unit name to not overflow
- *
- * @return static|CarbonInterface
- */
- public function addUnitNoOverflow($valueUnit, $value, $overflowUnit);
-
- /**
- * Get the difference in a human readable format in the current locale from an other
- * instance given to now
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single part)
- * @param int $options human diff options
- *
- * @return string
- */
- public function ago($syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Modify the current instance to the average of a given instance (default now) and the current instance
- * (second-precision).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date
- *
- * @return static|CarbonInterface
- */
- public function average($date = null);
-
- /**
- * Determines if the instance is between two others
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- * @param bool $equal Indicates if an equal to comparison should be done
- *
- * @return bool
- */
- public function between($date1, $date2, $equal = true): bool;
-
- /**
- * Returns either the close date "Friday 15h30", or a calendar date "10/09/2017" is farthest than 7 days from now.
- *
- * @param Carbon|\DateTimeInterface|string|null $referenceTime
- * @param array $formats
- *
- * @return string
- */
- public function calendar($referenceTime = null, array $formats = []);
-
- /**
- * Cast the current instance into the given class.
- *
- * @param string $className The $className::instance() method will be called to cast the current object.
- *
- * @return object
- */
- public function cast(string $className);
-
- /**
- * Ceil the current instance second with given precision if specified.
- *
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function ceil($precision = 1);
-
- /**
- * Ceil the current instance at the given unit with given precision if specified.
- *
- * @param string $unit
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function ceilUnit($unit, $precision = 1);
-
- /**
- * Ceil the current instance week.
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return CarbonInterface
- */
- public function ceilWeek($weekStartsAt = null);
-
- /**
- * @alias copy
- *
- * Get a copy of the instance.
- *
- * @return static|CarbonInterface
- */
- public function clone();
-
- /**
- * Get the closest date from the instance (second-precision).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- *
- * @return static|CarbonInterface
- */
- public function closest($date1, $date2);
-
- /**
- * Get a copy of the instance.
- *
- * @return static|CarbonInterface
- */
- public function copy();
-
- /**
- * Create a new Carbon instance from a specific date and time.
- *
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- *
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- *
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param int|null $hour
- * @param int|null $minute
- * @param int|null $second
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null);
-
- /**
- * Create a Carbon instance from just a date. The time portion is set to now.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function createFromDate($year = null, $month = null, $day = null, $tz = null);
-
- /**
- * Create a Carbon instance from a specific format.
- *
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromFormat($format, $time, $tz = null);
-
- /**
- * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
- *
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz optional timezone
- * @param string|null $locale locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use)
- * @param \Symfony\Component\Translation\TranslatorInterface $translator optional custom translator to use for macro-formats
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null);
-
- /**
- * Create a Carbon instance from a specific format and a string in a given language.
- *
- * @param string $format Datetime format
- * @param string $locale
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromLocaleFormat($format, $locale, $time, $tz = null);
-
- /**
- * Create a Carbon instance from a specific ISO format and a string in a given language.
- *
- * @param string $format Datetime ISO format
- * @param string $locale
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromLocaleIsoFormat($format, $locale, $time, $tz = null);
-
- /**
- * Create a Carbon instance from just a time. The date portion is set to today.
- *
- * @param int|null $hour
- * @param int|null $minute
- * @param int|null $second
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null);
-
- /**
- * Create a Carbon instance from a time string. The date portion is set to today.
- *
- * @param string $time
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimeString($time, $tz = null);
-
- /**
- * Create a Carbon instance from a timestamp.
- *
- * @param int $timestamp
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimestamp($timestamp, $tz = null);
-
- /**
- * Create a Carbon instance from a timestamp in milliseconds.
- *
- * @param int $timestamp
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimestampMs($timestamp, $tz = null);
-
- /**
- * Create a Carbon instance from an UTC timestamp.
- *
- * @param int $timestamp
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimestampUTC($timestamp);
-
- /**
- * Create a Carbon instance from just a date. The time portion is set to midnight.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null);
-
- /**
- * Create a new safe Carbon instance from a specific date and time.
- *
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- *
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- *
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- *
- * If one of the set values is not valid, an \InvalidArgumentException
- * will be thrown.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param int|null $hour
- * @param int|null $minute
- * @param int|null $second
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \Carbon\Exceptions\InvalidDateException|\InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null);
-
- /**
- * Get/set the day of year.
- *
- * @param int|null $value new value for day of year if using as setter.
- *
- * @return static|CarbonInterface|int
- */
- public function dayOfYear($value = null);
-
- /**
- * Get the difference as a CarbonInterval instance
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return CarbonInterval
- */
- public function diffAsCarbonInterval($date = null, $absolute = true);
-
- /**
- * Get the difference by the given interval using a filter closure
- *
- * @param CarbonInterval $ci An interval to traverse by
- * @param Closure $callback
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffFiltered(CarbonInterval $ci, \Closure $callback, $date = null, $absolute = true);
-
- /**
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- *
- * @example
- * ```
- * echo Carbon::tomorrow()->diffForHumans() . "\n";
- * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
- * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
- * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
- * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
- * ```
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Get the difference in days
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInDays($date = null, $absolute = true);
-
- /**
- * Get the difference in days using a filter closure
- *
- * @param Closure $callback
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInDaysFiltered(\Closure $callback, $date = null, $absolute = true);
-
- /**
- * Get the difference in hours.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInHours($date = null, $absolute = true);
-
- /**
- * Get the difference in hours using a filter closure
- *
- * @param Closure $callback
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInHoursFiltered(\Closure $callback, $date = null, $absolute = true);
-
- /**
- * Get the difference in microseconds.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMicroseconds($date = null, $absolute = true);
-
- /**
- * Get the difference in milliseconds.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMilliseconds($date = null, $absolute = true);
-
- /**
- * Get the difference in minutes.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMinutes($date = null, $absolute = true);
-
- /**
- * Get the difference in months
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMonths($date = null, $absolute = true);
-
- /**
- * Get the difference in hours using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealHours($date = null, $absolute = true);
-
- /**
- * Get the difference in microseconds using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealMicroseconds($date = null, $absolute = true);
-
- /**
- * Get the difference in milliseconds using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealMilliseconds($date = null, $absolute = true);
-
- /**
- * Get the difference in minutes using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealMinutes($date = null, $absolute = true);
-
- /**
- * Get the difference in seconds using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealSeconds($date = null, $absolute = true);
-
- /**
- * Get the difference in seconds.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInSeconds($date = null, $absolute = true);
-
- /**
- * Get the difference in weekdays
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInWeekdays($date = null, $absolute = true);
-
- /**
- * Get the difference in weekend days using a filter
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInWeekendDays($date = null, $absolute = true);
-
- /**
- * Get the difference in weeks
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInWeeks($date = null, $absolute = true);
-
- /**
- * Get the difference in years
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInYears($date = null, $absolute = true);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * @param int $humanDiffOption
- */
- public static function disableHumanDiffOption($humanDiffOption);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * @param int $humanDiffOption
- */
- public static function enableHumanDiffOption($humanDiffOption);
-
- /**
- * Modify to end of current given unit.
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->startOf('month')
- * ->endOf('week', Carbon::FRIDAY);
- * ```
- *
- * @param string $unit
- * @param array<int, mixed> $params
- *
- * @return static|CarbonInterface
- */
- public function endOf($unit, ...$params);
-
- /**
- * Resets the date to end of the century and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfCentury();
-
- /**
- * Resets the time to 23:59:59.999999 end of day
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfDay();
-
- /**
- * Resets the date to end of the decade and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfDecade();
-
- /**
- * Modify to end of current hour, minutes and seconds become 59
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfHour();
-
- /**
- * Resets the date to end of the century and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfMillennium();
-
- /**
- * Modify to end of current minute, seconds become 59
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfMinute();
-
- /**
- * Resets the date to end of the month and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfMonth();
-
- /**
- * Resets the date to end of the quarter and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfQuarter();
-
- /**
- * Modify to end of current second, microseconds become 999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->endOfSecond()
- * ->format('H:i:s.u');
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfSecond();
-
- /**
- * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n";
- * ```
- *
- * @param int $weekEndsAt optional start allow you to specify the day of week to use to end the week
- *
- * @return static|CarbonInterface
- */
- public function endOfWeek($weekEndsAt = null);
-
- /**
- * Resets the date to end of the year and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfYear();
-
- /**
- * Determines if the instance is equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see equalTo()
- *
- * @return bool
- */
- public function eq($date): bool;
-
- /**
- * Determines if the instance is equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function equalTo($date): bool;
-
- /**
- * Set the current locale to the given, execute the passed function, reset the locale to previous one,
- * then return the result of the closure (or null if the closure was void).
- *
- * @param string $locale locale ex. en
- * @param callable $func
- *
- * @return mixed
- */
- public static function executeWithLocale($locale, $func);
-
- /**
- * Get the farthest date from the instance (second-precision).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- *
- * @return static|CarbonInterface
- */
- public function farthest($date1, $date2);
-
- /**
- * Modify to the first occurrence of a given day of the week
- * in the current month. If no dayOfWeek is provided, modify to the
- * first day of the current month. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function firstOfMonth($dayOfWeek = null);
-
- /**
- * Modify to the first occurrence of a given day of the week
- * in the current quarter. If no dayOfWeek is provided, modify to the
- * first day of the current quarter. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function firstOfQuarter($dayOfWeek = null);
-
- /**
- * Modify to the first occurrence of a given day of the week
- * in the current year. If no dayOfWeek is provided, modify to the
- * first day of the current year. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function firstOfYear($dayOfWeek = null);
-
- /**
- * Get the difference in days as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInDays($date = null, $absolute = true);
-
- /**
- * Get the difference in hours as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInHours($date = null, $absolute = true);
-
- /**
- * Get the difference in minutes as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInMinutes($date = null, $absolute = true);
-
- /**
- * Get the difference in months as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInMonths($date = null, $absolute = true);
-
- /**
- * Get the difference in days as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealDays($date = null, $absolute = true);
-
- /**
- * Get the difference in hours as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealHours($date = null, $absolute = true);
-
- /**
- * Get the difference in minutes as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealMinutes($date = null, $absolute = true);
-
- /**
- * Get the difference in months as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealMonths($date = null, $absolute = true);
-
- /**
- * Get the difference in seconds as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealSeconds($date = null, $absolute = true);
-
- /**
- * Get the difference in year as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealYears($date = null, $absolute = true);
-
- /**
- * Get the difference in seconds as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInSeconds($date = null, $absolute = true);
-
- /**
- * Get the difference in year as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInYears($date = null, $absolute = true);
-
- /**
- * Round the current instance second with given precision if specified.
- *
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function floor($precision = 1);
-
- /**
- * Truncate the current instance at the given unit with given precision if specified.
- *
- * @param string $unit
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function floorUnit($unit, $precision = 1);
-
- /**
- * Truncate the current instance week.
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return CarbonInterface
- */
- public function floorWeek($weekStartsAt = null);
-
- /**
- * Format the instance with the current locale. You can set the current
- * locale using setlocale() http://php.net/setlocale.
- *
- * @param string $format
- *
- * @return string
- */
- public function formatLocalized($format);
-
- /**
- * @alias diffForHumans
- *
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Get the difference in a human readable format in the current locale from current
- * instance to now.
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function fromNow($syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Create an instance from a serialized string.
- *
- * @param string $value
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function fromSerialized($value);
-
- /**
- * Register a custom macro.
- *
- * @param object|callable $macro
- * @param int $priority marco with higher priority is tried first
- *
- * @return void
- */
- public static function genericMacro($macro, $priority = 0);
-
- /**
- * Get a part of the Carbon object
- *
- * @param string $name
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return string|int|bool|\DateTimeZone|null
- */
- public function get($name);
-
- /**
- * Returns the alternative number if available in the current locale.
- *
- * @param string $key date property
- *
- * @return string
- */
- public function getAltNumber(string $key): string;
-
- /**
- * Returns the list of internally available locales and already loaded custom locales.
- * (It will ignore custom translator dynamic loading.)
- *
- * @return array
- */
- public static function getAvailableLocales();
-
- /**
- * Returns list of Language object for each available locale. This object allow you to get the ISO name, native
- * name, region and variant of the locale.
- *
- * @return Language[]
- */
- public static function getAvailableLocalesInfo();
-
- /**
- * Returns list of calendar formats for ISO formatting.
- *
- * @param string|null $locale current locale used if null
- *
- * @return array
- */
- public function getCalendarFormats($locale = null);
-
- /**
- * Get the days of the week
- *
- * @return array
- */
- public static function getDays();
-
- /**
- * Get the fallback locale.
- *
- * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
- *
- * @return string|null
- */
- public static function getFallbackLocale();
-
- /**
- * List of replacements from date() format to isoFormat().
- *
- * @return array
- */
- public static function getFormatsToIsoReplacements();
-
- /**
- * Return default humanDiff() options (merged flags as integer).
- *
- * @return int
- */
- public static function getHumanDiffOptions();
-
- /**
- * Returns list of locale formats for ISO formatting.
- *
- * @param string|null $locale current locale used if null
- *
- * @return array
- */
- public function getIsoFormats($locale = null);
-
- /**
- * Returns list of locale units for ISO formatting.
- *
- * @return array
- */
- public static function getIsoUnits();
-
- /**
- * {@inheritdoc}
- */
- public static function getLastErrors();
-
- /**
- * Get the translator of the current instance or the default if none set.
- *
- * @return \Symfony\Component\Translation\TranslatorInterface
- */
- public function getLocalTranslator();
-
- /**
- * Get the current translator locale.
- *
- * @return string
- */
- public static function getLocale();
-
- /**
- * get midday/noon hour
- *
- * @return int
- */
- public static function getMidDayAt();
-
- /**
- * Returns the offset hour and minute formatted with +/- and a given separator (":" by default).
- * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first
- * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something
- * like "-12:00".
- *
- * @param string $separator string to place between hours and minutes (":" by default)
- *
- * @return string
- */
- public function getOffsetString($separator = ':');
-
- /**
- * Returns a unit of the instance padded with 0 by default or any other string if specified.
- *
- * @param string $unit Carbon unit name
- * @param int $length Length of the output (2 by default)
- * @param string $padString String to use for padding ("0" by default)
- * @param int $padType Side(s) to pad (STR_PAD_LEFT by default)
- *
- * @return string
- */
- public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = 0);
-
- /**
- * Returns a timestamp rounded with the given precision (6 by default).
- *
- * @example getPreciseTimestamp() 1532087464437474 (microsecond maximum precision)
- * @example getPreciseTimestamp(6) 1532087464437474
- * @example getPreciseTimestamp(5) 153208746443747 (1/100000 second precision)
- * @example getPreciseTimestamp(4) 15320874644375 (1/10000 second precision)
- * @example getPreciseTimestamp(3) 1532087464437 (millisecond precision)
- * @example getPreciseTimestamp(2) 153208746444 (1/100 second precision)
- * @example getPreciseTimestamp(1) 15320874644 (1/10 second precision)
- * @example getPreciseTimestamp(0) 1532087464 (second precision)
- * @example getPreciseTimestamp(-1) 153208746 (10 second precision)
- * @example getPreciseTimestamp(-2) 15320875 (100 second precision)
- *
- * @param int $precision
- *
- * @return float
- */
- public function getPreciseTimestamp($precision = 6);
-
- /**
- * Returns current local settings.
- *
- * @return array
- */
- public function getSettings();
-
- /**
- * Get the Carbon instance (real or mock) to be returned when a "now"
- * instance is created.
- *
- * @return static|CarbonInterface the current instance used for testing
- */
- public static function getTestNow();
-
- /**
- * Get the translation of the current week day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- * @param string $keySuffix "", "_short" or "_min"
- * @param string|null $defaultValue default value if translation missing
- *
- * @return string
- */
- public function getTranslatedDayName($context = null, $keySuffix = '', $defaultValue = null);
-
- /**
- * Get the translation of the current abbreviated week day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- *
- * @return string
- */
- public function getTranslatedMinDayName($context = null);
-
- /**
- * Get the translation of the current month day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- * @param string $keySuffix "" or "_short"
- * @param string|null $defaultValue default value if translation missing
- *
- * @return string
- */
- public function getTranslatedMonthName($context = null, $keySuffix = '', $defaultValue = null);
-
- /**
- * Get the translation of the current short week day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- *
- * @return string
- */
- public function getTranslatedShortDayName($context = null);
-
- /**
- * Get the translation of the current short month day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- *
- * @return string
- */
- public function getTranslatedShortMonthName($context = null);
-
- /**
- * Returns raw translation message for a given key.
- *
- * @param string $key key to find
- * @param string|null $locale current locale used if null
- * @param string|null $default default value if translation returns the key
- * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use
- *
- * @return string
- */
- public function getTranslationMessage(string $key, string $locale = null, string $default = null, $translator = null);
-
- /**
- * Returns raw translation message for a given key.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use
- * @param string $key key to find
- * @param string|null $locale current locale used if null
- * @param string|null $default default value if translation returns the key
- *
- * @return string
- */
- public static function getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null);
-
- /**
- * Get the default translator instance in use.
- *
- * @return \Symfony\Component\Translation\TranslatorInterface
- */
- public static function getTranslator();
-
- /**
- * Get the last day of week
- *
- * @return int
- */
- public static function getWeekEndsAt();
-
- /**
- * Get the first day of week
- *
- * @return int
- */
- public static function getWeekStartsAt();
-
- /**
- * Get weekend days
- *
- * @return array
- */
- public static function getWeekendDays();
-
- /**
- * Determines if the instance is greater (after) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function greaterThan($date): bool;
-
- /**
- * Determines if the instance is greater (after) than or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function greaterThanOrEqualTo($date): bool;
-
- /**
- * Determines if the instance is greater (after) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see greaterThan()
- *
- * @return bool
- */
- public function gt($date): bool;
-
- /**
- * Determines if the instance is greater (after) than or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see greaterThanOrEqualTo()
- *
- * @return bool
- */
- public function gte($date): bool;
-
- /**
- * Checks if the (date)time string is in a given format.
- *
- * @param string $date
- * @param string $format
- *
- * @return bool
- */
- public static function hasFormat($date, $format);
-
- /**
- * Checks if macro is registered.
- *
- * @param string $name
- *
- * @return bool
- */
- public static function hasMacro($name);
-
- /**
- * Determine if a time string will produce a relative date.
- *
- * @param string $time
- *
- * @return bool true if time match a relative date, false if absolute or invalid time string
- */
- public static function hasRelativeKeywords($time);
-
- /**
- * Determine if there is a valid test instance set. A valid test instance
- * is anything that is not null.
- *
- * @return bool true if there is a test instance, otherwise false
- */
- public static function hasTestNow();
-
- /**
- * Create a Carbon instance from a DateTime one.
- *
- * @param \DateTimeInterface $date
- *
- * @return static|CarbonInterface
- */
- public static function instance($date);
-
- /**
- * Determines if the instance is greater (after) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see greaterThan()
- *
- * @return bool
- */
- public function isAfter($date): bool;
-
- /**
- * Determines if the instance is less (before) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see lessThan()
- *
- * @return bool
- */
- public function isBefore($date): bool;
-
- /**
- * Determines if the instance is between two others
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- * @param bool $equal Indicates if an equal to comparison should be done
- *
- * @return bool
- */
- public function isBetween($date1, $date2, $equal = true): bool;
-
- /**
- * Check if its the birthday. Compares the date/month values of the two dates.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
- *
- * @return bool
- */
- public function isBirthday($date = null);
-
- /**
- * Determines if the instance is in the current unit given.
- *
- * @param string $unit The unit to test.
- *
- * @throws \BadMethodCallException
- *
- * @return bool
- */
- public function isCurrentUnit($unit);
-
- /**
- * Checks if this day is a specific day of the week.
- *
- * @param int $dayOfWeek
- *
- * @return bool
- */
- public function isDayOfWeek($dayOfWeek);
-
- /**
- * Check if the instance is end of day.
- *
- * @param bool $checkMicroseconds check time at microseconds precision
- *
- * @return bool
- */
- public function isEndOfDay($checkMicroseconds = false);
-
- /**
- * Determines if the instance is in the future, ie. greater (after) than now.
- *
- * @return bool
- */
- public function isFuture();
-
- /**
- * Returns true if the current class/instance is immutable.
- *
- * @return bool
- */
- public static function isImmutable();
-
- /**
- * Check if today is the last day of the Month
- *
- * @return bool
- */
- public function isLastOfMonth();
-
- /**
- * Determines if the instance is a leap year.
- *
- * @return bool
- */
- public function isLeapYear();
-
- /**
- * Determines if the instance is a long year
- *
- * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
- *
- * @return bool
- */
- public function isLongYear();
-
- /**
- * Check if the instance is midday.
- *
- * @return bool
- */
- public function isMidday();
-
- /**
- * Check if the instance is start of day / midnight.
- *
- * @return bool
- */
- public function isMidnight();
-
- /**
- * Returns true if a property can be changed via setter.
- *
- * @param string $unit
- *
- * @return bool
- */
- public static function isModifiableUnit($unit);
-
- public static function isMutable();
-
- /**
- * Determines if the instance is in the past, ie. less (before) than now.
- *
- * @return bool
- */
- public function isPast();
-
- /**
- * Compares the formatted values of the two dates.
- *
- * @param string $format date formats to compare.
- * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day.
- *
- * @throws \InvalidArgumentException
- *
- * @return bool
- */
- public function isSameAs($format, $date = null);
-
- /**
- * Checks if the passed in date is in the same month as the instance´s month.
- *
- * Note that this defaults to only comparing the month while ignoring the year.
- * To test if it is the same exact month of the same year, pass in true as the second parameter.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
- * @param bool $ofSameYear Check if it is the same month in the same year.
- *
- * @return bool
- */
- public function isSameMonth($date = null, $ofSameYear = true);
-
- /**
- * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
- * @param bool $ofSameYear Check if it is the same month in the same year.
- *
- * @return bool
- */
- public function isSameQuarter($date = null, $ofSameYear = true);
-
- /**
- * Determines if the instance is in the current unit given.
- *
- * @param string $unit singular unit string
- * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day.
- *
- * @throws \InvalidArgumentException
- *
- * @return bool
- */
- public function isSameUnit($unit, $date = null);
-
- /**
- * Check if the instance is start of day / midnight.
- *
- * @param bool $checkMicroseconds check time at microseconds precision
- *
- * @return bool
- */
- public function isStartOfDay($checkMicroseconds = false);
-
- /**
- * Returns true if the strict mode is globally in use, false else.
- * (It can be overridden in specific instances.)
- *
- * @return bool
- */
- public static function isStrictModeEnabled();
-
- /**
- * Determines if the instance is today.
- *
- * @return bool
- */
- public function isToday();
-
- /**
- * Determines if the instance is tomorrow.
- *
- * @return bool
- */
- public function isTomorrow();
-
- /**
- * Determines if the instance is a weekday.
- *
- * @return bool
- */
- public function isWeekday();
-
- /**
- * Determines if the instance is a weekend day.
- *
- * @return bool
- */
- public function isWeekend();
-
- /**
- * Determines if the instance is yesterday.
- *
- * @return bool
- */
- public function isYesterday();
-
- /**
- * Format in the current language using ISO replacement patterns.
- *
- * @param string $format
- * @param string|null $originalFormat provide context if a chunk has been passed alone
- *
- * @return string
- */
- public function isoFormat(string $format, string $originalFormat = null): string;
-
- /**
- * Get/set the week number using given first day of week and first
- * day of year included in the first week. Or use ISO format if no settings
- * given.
- *
- * @param int|null $week
- * @param int|null $dayOfWeek
- * @param int|null $dayOfYear
- *
- * @return int|static
- */
- public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null);
-
- /**
- * Set/get the week number of year using given first day of week and first
- * day of year included in the first week. Or use ISO format if no settings
- * given.
- *
- * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int|static
- */
- public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null);
-
- /**
- * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday).
- *
- * @param int|null $value new value for weekday if using as setter.
- *
- * @return static|CarbonInterface|int
- */
- public function isoWeekday($value = null);
-
- /**
- * Get the number of weeks of the current week-year using given first day of week and first
- * day of year included in the first week. Or use ISO format if no settings
- * given.
- *
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int
- */
- public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null);
-
- /**
- * Prepare the object for JSON serialization.
- *
- * @return array|string
- */
- public function jsonSerialize();
-
- /**
- * Modify to the last occurrence of a given day of the week
- * in the current month. If no dayOfWeek is provided, modify to the
- * last day of the current month. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function lastOfMonth($dayOfWeek = null);
-
- /**
- * Modify to the last occurrence of a given day of the week
- * in the current quarter. If no dayOfWeek is provided, modify to the
- * last day of the current quarter. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function lastOfQuarter($dayOfWeek = null);
-
- /**
- * Modify to the last occurrence of a given day of the week
- * in the current year. If no dayOfWeek is provided, modify to the
- * last day of the current year. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function lastOfYear($dayOfWeek = null);
-
- /**
- * Determines if the instance is less (before) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function lessThan($date): bool;
-
- /**
- * Determines if the instance is less (before) or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function lessThanOrEqualTo($date): bool;
-
- /**
- * Get/set the locale for the current instance.
- *
- * @param string|null $locale
- * @param string[] ...$fallbackLocales
- *
- * @return $this|string
- */
- public function locale(string $locale = null, ...$fallbackLocales);
-
- /**
- * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
- * Support is considered enabled if the 3 words are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasDiffOneDayWords($locale);
-
- /**
- * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasDiffSyntax($locale);
-
- /**
- * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
- * Support is considered enabled if the 2 words are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasDiffTwoDayWords($locale);
-
- /**
- * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasPeriodSyntax($locale);
-
- /**
- * Returns true if the given locale is internally supported and has short-units support.
- * Support is considered enabled if either year, day or hour has a short variant translated.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasShortUnits($locale);
-
- /**
- * Determines if the instance is less (before) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see lessThan()
- *
- * @return bool
- */
- public function lt($date): bool;
-
- /**
- * Determines if the instance is less (before) or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see lessThanOrEqualTo()
- *
- * @return bool
- */
- public function lte($date): bool;
-
- /**
- * Register a custom macro.
- *
- * @example
- * ```
- * $userSettings = [
- * 'locale' => 'pt',
- * 'timezone' => 'America/Sao_Paulo',
- * ];
- * Carbon::macro('userFormat', function () use ($userSettings) {
- * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
- * });
- * echo Carbon::yesterday()->hours(11)->userFormat();
- * ```
- *
- * @param string $name
- * @param object|callable $macro
- *
- * @return void
- */
- public static function macro($name, $macro);
-
- /**
- * Make a Carbon instance from given variable if possible.
- *
- * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
- * and recurrences). Throw an exception for invalid format, but otherwise return null.
- *
- * @param mixed $var
- *
- * @return static|CarbonInterface|null
- */
- public static function make($var);
-
- /**
- * Get the maximum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return static|CarbonInterface
- */
- public function max($date = null);
-
- /**
- * Create a Carbon instance for the greatest supported date.
- *
- * @return static|CarbonInterface
- */
- public static function maxValue();
-
- /**
- * Get the maximum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see max()
- *
- * @return static|CarbonInterface
- */
- public function maximum($date = null);
-
- /**
- * Return the meridiem of the current time in the current locale.
- *
- * @param bool $isLower if true, returns lowercase variant if available in the current locale.
- *
- * @return string
- */
- public function meridiem(bool $isLower = false): string;
-
- /**
- * Modify to midday, default to self::$midDayAt
- *
- * @return static|CarbonInterface
- */
- public function midDay();
-
- /**
- * Get the minimum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return static|CarbonInterface
- */
- public function min($date = null);
-
- /**
- * Create a Carbon instance for the lowest supported date.
- *
- * @return static|CarbonInterface
- */
- public static function minValue();
-
- /**
- * Get the minimum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see min()
- *
- * @return static|CarbonInterface
- */
- public function minimum($date = null);
-
- /**
- * Mix another object into the class.
- *
- * @example
- * ```
- * Carbon::mixin(new class {
- * public function addMoon() {
- * return function () {
- * return $this->addDays(30);
- * };
- * }
- * public function subMoon() {
- * return function () {
- * return $this->subDays(30);
- * };
- * }
- * });
- * $fullMoon = Carbon::create('2018-12-22');
- * $nextFullMoon = $fullMoon->addMoon();
- * $blackMoon = Carbon::create('2019-01-06');
- * $previousBlackMoon = $blackMoon->subMoon();
- * echo "$nextFullMoon\n";
- * echo "$previousBlackMoon\n";
- * ```
- *
- * @param object $mixin
- *
- * @throws \ReflectionException
- *
- * @return void
- */
- public static function mixin($mixin);
-
- /**
- * call \DateTime::modify if mutable or \DateTimeImmutable::modify else.
- *
- * @see https://php.net/manual/en/datetime.modify.php
- */
- public function modify($modify);
-
- /**
- * Determines if the instance is not equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see notEqualTo()
- *
- * @return bool
- */
- public function ne($date): bool;
-
- /**
- * Modify to the next occurrence of a given day of the week.
- * If no dayOfWeek is provided, modify to the next occurrence
- * of the current day of the week. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function next($dayOfWeek = null);
-
- /**
- * Go forward to the next weekday.
- *
- * @return static|CarbonInterface
- */
- public function nextWeekday();
-
- /**
- * Go forward to the next weekend day.
- *
- * @return static|CarbonInterface
- */
- public function nextWeekendDay();
-
- /**
- * Determines if the instance is not equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function notEqualTo($date): bool;
-
- /**
- * Get a Carbon instance for the current date and time.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function now($tz = null);
-
- /**
- * Returns a present instance in the same timezone.
- *
- * @return static|CarbonInterface
- */
- public function nowWithSameTz();
-
- /**
- * Modify to the given occurrence of a given day of the week
- * in the current month. If the calculated occurrence is outside the scope
- * of the current month, then return false and no modifications are made.
- * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int $nth
- * @param int $dayOfWeek
- *
- * @return mixed
- */
- public function nthOfMonth($nth, $dayOfWeek);
-
- /**
- * Modify to the given occurrence of a given day of the week
- * in the current quarter. If the calculated occurrence is outside the scope
- * of the current quarter, then return false and no modifications are made.
- * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int $nth
- * @param int $dayOfWeek
- *
- * @return mixed
- */
- public function nthOfQuarter($nth, $dayOfWeek);
-
- /**
- * Modify to the given occurrence of a given day of the week
- * in the current year. If the calculated occurrence is outside the scope
- * of the current year, then return false and no modifications are made.
- * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int $nth
- * @param int $dayOfWeek
- *
- * @return mixed
- */
- public function nthOfYear($nth, $dayOfWeek);
-
- /**
- * Return a property with its ordinal.
- *
- * @param string $key
- * @param string|null $period
- *
- * @return string
- */
- public function ordinal(string $key, string $period = null): string;
-
- /**
- * Create a carbon instance from a string.
- *
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- *
- * @param string|null $time
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function parse($time = null, $tz = null);
-
- /**
- * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
- *
- * @param string $time
- * @param string $locale
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function parseFromLocale($time, $locale, $tz = null);
-
- /**
- * Returns standardized plural of a given singular/plural unit name (in English).
- *
- * @param string $unit
- *
- * @return string
- */
- public static function pluralUnit(string $unit): string;
-
- /**
- * Modify to the previous occurrence of a given day of the week.
- * If no dayOfWeek is provided, modify to the previous occurrence
- * of the current day of the week. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function previous($dayOfWeek = null);
-
- /**
- * Go backward to the previous weekday.
- *
- * @return static|CarbonInterface
- */
- public function previousWeekday();
-
- /**
- * Go backward to the previous weekend day.
- *
- * @return static|CarbonInterface
- */
- public function previousWeekendDay();
-
- /**
- * Create a Carbon instance from a specific format.
- *
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function rawCreateFromFormat($format, $time, $tz = null);
-
- /**
- * @see https://php.net/manual/en/datetime.format.php
- *
- * @param string $format
- *
- * @return string
- */
- public function rawFormat($format);
-
- /**
- * Create a carbon instance from a string.
- *
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- *
- * @param string|null $time
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function rawParse($time = null, $tz = null);
-
- /**
- * Remove all macros and generic macros.
- */
- public static function resetMacros();
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Reset the month overflow behavior.
- *
- * @return void
- */
- public static function resetMonthsOverflow();
-
- /**
- * Reset the format used to the default when type juggling a Carbon instance to a string
- *
- * @return void
- */
- public static function resetToStringFormat();
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Reset the month overflow behavior.
- *
- * @return void
- */
- public static function resetYearsOverflow();
-
- /**
- * Round the current instance second with given precision if specified.
- *
- * @param float|int $precision
- * @param string $function
- *
- * @return CarbonInterface
- */
- public function round($precision = 1, $function = 'round');
-
- /**
- * Round the current instance at the given unit with given precision if specified and the given function.
- *
- * @param string $unit
- * @param float|int $precision
- * @param string $function
- *
- * @return CarbonInterface
- */
- public function roundUnit($unit, $precision = 1, $function = 'round');
-
- /**
- * Round the current instance week.
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return CarbonInterface
- */
- public function roundWeek($weekStartsAt = null);
-
- /**
- * The number of seconds since midnight.
- *
- * @return int
- */
- public function secondsSinceMidnight();
-
- /**
- * The number of seconds until 23:59:59.
- *
- * @return int
- */
- public function secondsUntilEndOfDay();
-
- /**
- * Return a serialized string of the instance.
- *
- * @return string
- */
- public function serialize();
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather transform Carbon object before the serialization.
- *
- * JSON serialize all Carbon instances using the given callback.
- *
- * @param callable $callback
- *
- * @return void
- */
- public static function serializeUsing($callback);
-
- /**
- * Set a part of the Carbon object
- *
- * @param string|array $name
- * @param string|int|\DateTimeZone $value
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return $this
- */
- public function set($name, $value = null);
-
- public function setDate($year, $month, $day);
-
- /**
- * Set the year, month, and date for this instance to that of the passed instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface $date now if null
- *
- * @return static
- */
- public function setDateFrom($date = null);
-
- /**
- * Set the date and time all together.
- *
- * @param int $year
- * @param int $month
- * @param int $day
- * @param int $hour
- * @param int $minute
- * @param int $second
- * @param int $microseconds
- *
- * @return static|CarbonInterface
- */
- public function setDateTime($year, $month, $day, $hour, $minute, $second = 0, $microseconds = 0);
-
- /**
- * Set the date and time for this instance to that of the passed instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface $date
- *
- * @return static
- */
- public function setDateTimeFrom($date = null);
-
- /**
- * Set the fallback locale.
- *
- * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
- *
- * @param string $locale
- */
- public static function setFallbackLocale($locale);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * @param int $humanDiffOptions
- */
- public static function setHumanDiffOptions($humanDiffOptions);
-
- /**
- * call \DateTime::setISODate if mutable or \DateTimeImmutable::setISODate else.
- *
- * @see https://php.net/manual/en/datetime.setisodate.php
- */
- public function setISODate($year, $week, $day = 1);
-
- /**
- * Set the translator for the current instance.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- *
- * @return $this
- */
- public function setLocalTranslator(\Symfony\Component\Translation\TranslatorInterface $translator);
-
- /**
- * Set the current translator locale and indicate if the source locale file exists.
- * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function setLocale($locale);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
- * hour, test it explicitly:
- * $date->format('G') == 13
- * or to set explicitly to a given hour:
- * $date->setTime(13, 0, 0, 0)
- *
- * Set midday/noon hour
- *
- * @param int $hour midday hour
- *
- * @return void
- */
- public static function setMidDayAt($hour);
-
- /**
- * Set a Carbon instance (real or mock) to be returned when a "now"
- * instance is created. The provided instance will be returned
- * specifically under the following conditions:
- * - A call to the static now() method, ex. Carbon::now()
- * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
- * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
- * - When a string containing the desired time is passed to Carbon::parse().
- *
- * Note the timezone parameter was left out of the examples above and
- * has no affect as the mock value will be returned regardless of its value.
- *
- * To clear the test instance call this method using the default
- * parameter of null.
- *
- * /!\ Use this method for unit tests only.
- *
- * @param CarbonInterface|string|null $testNow real or mock Carbon instance
- */
- public static function setTestNow($testNow = null);
-
- /**
- * call \DateTime::setTime if mutable or \DateTimeImmutable::setTime else.
- *
- * @see https://php.net/manual/en/datetime.settime.php
- */
- public function setTime($hour, $minute, $second = 0, $microseconds = 0);
-
- /**
- * Set the hour, minute, second and microseconds for this instance to that of the passed instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface $date now if null
- *
- * @return static
- */
- public function setTimeFrom($date = null);
-
- /**
- * Set the time by time string.
- *
- * @param string $time
- *
- * @return static|CarbonInterface
- */
- public function setTimeFromTimeString($time);
-
- /**
- * call \DateTime::setTimestamp if mutable or \DateTimeImmutable::setTimestamp else.
- *
- * @see https://php.net/manual/en/datetime.settimestamp.php
- */
- public function setTimestamp($unixtimestamp);
-
- /**
- * Set the instance's timezone from a string or object.
- *
- * @param \DateTimeZone|string $value
- *
- * @return static|CarbonInterface
- */
- public function setTimezone($value);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
- * use other method or custom format passed to format() method if you need to dump an other string
- * format.
- *
- * Set the default format used when type juggling a Carbon instance to a string
- *
- * @param string|Closure|null $format
- *
- * @return void
- */
- public static function setToStringFormat($format);
-
- /**
- * Set the default translator instance to use.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- *
- * @return void
- */
- public static function setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator);
-
- /**
- * Set specified unit to new given value.
- *
- * @param string $unit year, month, day, hour, minute, second or microsecond
- * @param int $value new value for given unit
- *
- * @return static
- */
- public function setUnit($unit, $value = null);
-
- /**
- * Set any unit to a new value without overflowing current other unit given.
- *
- * @param string $valueUnit unit name to modify
- * @param int $value new value for the input unit
- * @param string $overflowUnit unit name to not overflow
- *
- * @return static|CarbonInterface
- */
- public function setUnitNoOverflow($valueUnit, $value, $overflowUnit);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use UTF-8 language packages on every machine.
- *
- * Set if UTF8 will be used for localized date/time.
- *
- * @param bool $utf8
- */
- public static function setUtf8($utf8);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
- * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
- * start of week according to current locale selected and implicitly the end of week.
- *
- * Set the last day of week
- *
- * @param int $day
- *
- * @return void
- */
- public static function setWeekEndsAt($day);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
- * 'first_day_of_week' locale setting to change the start of week according to current locale
- * selected and implicitly the end of week.
- *
- * Set the first day of week
- *
- * @param int $day week start day
- *
- * @return void
- */
- public static function setWeekStartsAt($day);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider week-end is always saturday and sunday, and if you have some custom
- * week-end days to handle, give to those days an other name and create a macro for them:
- *
- * ```
- * Carbon::macro('isDayOff', function ($date) {
- * return $date->isSunday() || $date->isMonday();
- * });
- * Carbon::macro('isNotDayOff', function ($date) {
- * return !$date->isDayOff();
- * });
- * if ($someDate->isDayOff()) ...
- * if ($someDate->isNotDayOff()) ...
- * // Add 5 not-off days
- * $count = 5;
- * while ($someDate->isDayOff() || ($count-- > 0)) {
- * $someDate->addDay();
- * }
- * ```
- *
- * Set weekend days
- *
- * @param array $days
- *
- * @return void
- */
- public static function setWeekendDays($days);
-
- /**
- * Set specific options.
- * - strictMode: true|false|null
- * - monthOverflow: true|false|null
- * - yearOverflow: true|false|null
- * - humanDiffOptions: int|null
- * - toStringFormat: string|Closure|null
- * - toJsonFormat: string|Closure|null
- * - locale: string|null
- * - timezone: \DateTimeZone|string|int|null
- * - macros: array|null
- * - genericMacros: array|null
- *
- * @param array $settings
- *
- * @return $this
- */
- public function settings(array $settings);
-
- /**
- * Set the instance's timezone from a string or object and add/subtract the offset difference.
- *
- * @param \DateTimeZone|string $value
- *
- * @return static|CarbonInterface
- */
- public function shiftTimezone($value);
-
- /**
- * Get the month overflow global behavior (can be overridden in specific instances).
- *
- * @return bool
- */
- public static function shouldOverflowMonths();
-
- /**
- * Get the month overflow global behavior (can be overridden in specific instances).
- *
- * @return bool
- */
- public static function shouldOverflowYears();
-
- /**
- * @alias diffForHumans
- *
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- */
- public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Returns standardized singular of a given singular/plural unit name (in English).
- *
- * @param string $unit
- *
- * @return string
- */
- public static function singularUnit(string $unit): string;
-
- /**
- * Modify to start of current given unit.
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->startOf('month')
- * ->endOf('week', Carbon::FRIDAY);
- * ```
- *
- * @param string $unit
- * @param array<int, mixed> $params
- *
- * @return static|CarbonInterface
- */
- public function startOf($unit, ...$params);
-
- /**
- * Resets the date to the first day of the century and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfCentury();
-
- /**
- * Resets the time to 00:00:00 start of day
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfDay();
-
- /**
- * Resets the date to the first day of the decade and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfDecade();
-
- /**
- * Modify to start of current hour, minutes and seconds become 0
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfHour();
-
- /**
- * Resets the date to the first day of the century and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfMillennium();
-
- /**
- * Modify to start of current minute, seconds become 0
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfMinute();
-
- /**
- * Resets the date to the first day of the month and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfMonth();
-
- /**
- * Resets the date to the first day of the quarter and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfQuarter();
-
- /**
- * Modify to start of current second, microseconds become 0
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->startOfSecond()
- * ->format('H:i:s.u');
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfSecond();
-
- /**
- * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n";
- * ```
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return static|CarbonInterface
- */
- public function startOfWeek($weekStartsAt = null);
-
- /**
- * Resets the date to the first day of the year and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfYear();
-
- /**
- * Subtract given units or interval to the current instance.
- *
- * @example $date->sub('hour', 3)
- * @example $date->sub(15, 'days')
- * @example $date->sub(CarbonInterval::days(4))
- *
- * @param string|DateInterval $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function sub($unit, $value = 1, $overflow = null);
-
- public function subRealUnit($unit, $value = 1);
-
- /**
- * Subtract given units to the current instance.
- *
- * @param string $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function subUnit($unit, $value = 1, $overflow = null);
-
- /**
- * Subtract any unit to a new value without overflowing current other unit given.
- *
- * @param string $valueUnit unit name to modify
- * @param int $value amount to subtract to the input unit
- * @param string $overflowUnit unit name to not overflow
- *
- * @return static|CarbonInterface
- */
- public function subUnitNoOverflow($valueUnit, $value, $overflowUnit);
-
- /**
- * Subtract given units or interval to the current instance.
- *
- * @see sub()
- *
- * @param string|DateInterval $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function subtract($unit, $value = 1, $overflow = null);
-
- /**
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- *
- * @return string
- */
- public function timespan($other = null, $timezone = null);
-
- /**
- * Set the instance's timestamp.
- *
- * @param int $value
- *
- * @return static|CarbonInterface
- */
- public function timestamp($value);
-
- /**
- * @alias setTimezone
- *
- * @param \DateTimeZone|string $value
- *
- * @return static|CarbonInterface
- */
- public function timezone($value);
-
- /**
- * Get the difference in a human readable format in the current locale from an other
- * instance given (or now if null given) to current instance.
- *
- * When comparing a value in the past to default now:
- * 1 hour from now
- * 5 months from now
- *
- * When comparing a value in the future to default now:
- * 1 hour ago
- * 5 months ago
- *
- * When comparing a value in the past to another value:
- * 1 hour after
- * 5 months after
- *
- * When comparing a value in the future to another value:
- * 1 hour before
- * 5 months before
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Get default array representation.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toArray());
- * ```
- *
- * @return array
- */
- public function toArray();
-
- /**
- * Format the instance as ATOM
- *
- * @example
- * ```
- * echo Carbon::now()->toAtomString();
- * ```
- *
- * @return string
- */
- public function toAtomString();
-
- /**
- * Format the instance as COOKIE
- *
- * @example
- * ```
- * echo Carbon::now()->toCookieString();
- * ```
- *
- * @return string
- */
- public function toCookieString();
-
- /**
- * @alias toDateTime
- *
- * Return native DateTime PHP object matching the current instance.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toDate());
- * ```
- *
- * @return DateTime
- */
- public function toDate();
-
- /**
- * Format the instance as date
- *
- * @example
- * ```
- * echo Carbon::now()->toDateString();
- * ```
- *
- * @return string
- */
- public function toDateString();
-
- /**
- * Return native DateTime PHP object matching the current instance.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toDateTime());
- * ```
- *
- * @return DateTime
- */
- public function toDateTime();
-
- /**
- * Format the instance as date and time T-separated with no timezone
- *
- * @example
- * ```
- * echo Carbon::now()->toDateTimeLocalString();
- * ```
- *
- * @return string
- */
- public function toDateTimeLocalString();
-
- /**
- * Format the instance as date and time
- *
- * @example
- * ```
- * echo Carbon::now()->toDateTimeString();
- * ```
- *
- * @return string
- */
- public function toDateTimeString();
-
- /**
- * Format the instance with day, date and time
- *
- * @example
- * ```
- * echo Carbon::now()->toDayDateTimeString();
- * ```
- *
- * @return string
- */
- public function toDayDateTimeString();
-
- /**
- * Format the instance as a readable date
- *
- * @example
- * ```
- * echo Carbon::now()->toFormattedDateString();
- * ```
- *
- * @return string
- */
- public function toFormattedDateString();
-
- /**
- * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
- * 1977-04-22T01:00:00-05:00).
- *
- * @example
- * ```
- * echo Carbon::now('America/Toronto')->toISOString() . "\n";
- * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
- * ```
- *
- * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
- *
- * @return null|string
- */
- public function toISOString($keepOffset = false);
-
- /**
- * Return a immutable copy of the instance.
- *
- * @return CarbonImmutable
- */
- public function toImmutable();
-
- /**
- * Format the instance as ISO8601
- *
- * @example
- * ```
- * echo Carbon::now()->toIso8601String();
- * ```
- *
- * @return string
- */
- public function toIso8601String();
-
- /**
- * Convert the instance to UTC and return as Zulu ISO8601
- *
- * @example
- * ```
- * echo Carbon::now()->toIso8601ZuluString();
- * ```
- *
- * @return string
- */
- public function toIso8601ZuluString();
-
- /**
- * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
- *
- * @example
- * ```
- * echo Carbon::now('America/Toronto')->toJSON();
- * ```
- *
- * @return null|string
- */
- public function toJSON();
-
- /**
- * Return a mutable copy of the instance.
- *
- * @return Carbon
- */
- public function toMutable();
-
- /**
- * Get the difference in a human readable format in the current locale from an other
- * instance given to now
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single part)
- * @param int $options human diff options
- *
- * @return string
- */
- public function toNow($syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * Get default object representation.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toObject());
- * ```
- *
- * @return object
- */
- public function toObject();
-
- /**
- * Format the instance as RFC1036
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc1036String();
- * ```
- *
- * @return string
- */
- public function toRfc1036String();
-
- /**
- * Format the instance as RFC1123
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc1123String();
- * ```
- *
- * @return string
- */
- public function toRfc1123String();
-
- /**
- * Format the instance as RFC2822
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc2822String();
- * ```
- *
- * @return string
- */
- public function toRfc2822String();
-
- /**
- * Format the instance as RFC3339
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc3339String();
- * ```
- *
- * @return string
- */
- public function toRfc3339String();
-
- /**
- * Format the instance as RFC7231
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc7231String();
- * ```
- *
- * @return string
- */
- public function toRfc7231String();
-
- /**
- * Format the instance as RFC822
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc822String();
- * ```
- *
- * @return string
- */
- public function toRfc822String();
-
- /**
- * Format the instance as RFC850
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc850String();
- * ```
- *
- * @return string
- */
- public function toRfc850String();
-
- /**
- * Format the instance as RSS
- *
- * @example
- * ```
- * echo Carbon::now()->toRssString();
- * ```
- *
- * @return string
- */
- public function toRssString();
-
- /**
- * Returns english human readable complete date string.
- *
- * @example
- * ```
- * echo Carbon::now()->toString();
- * ```
- *
- * @return string
- */
- public function toString();
-
- /**
- * Format the instance as time
- *
- * @example
- * ```
- * echo Carbon::now()->toTimeString();
- * ```
- *
- * @return string
- */
- public function toTimeString();
-
- /**
- * Format the instance as W3C
- *
- * @example
- * ```
- * echo Carbon::now()->toW3cString();
- * ```
- *
- * @return string
- */
- public function toW3cString();
-
- /**
- * Create a Carbon instance for today.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function today($tz = null);
-
- /**
- * Create a Carbon instance for tomorrow.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function tomorrow($tz = null);
-
- /**
- * Translate using translation string or callback available.
- *
- * @param string $key
- * @param array $parameters
- * @param null $number
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- *
- * @return string
- */
- public function translate(string $key, array $parameters = [], $number = null, \Symfony\Component\Translation\TranslatorInterface $translator = null): string;
-
- /**
- * Translate a time string from a locale to an other.
- *
- * @param string $timeString time string to translate
- * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default)
- * @param string|null $to output locale of the result returned (`"en"` by default)
- * @param int $mode specify what to translate with options:
- * - CarbonInterface::TRANSLATE_ALL (default)
- * - CarbonInterface::TRANSLATE_MONTHS
- * - CarbonInterface::TRANSLATE_DAYS
- * - CarbonInterface::TRANSLATE_UNITS
- * - CarbonInterface::TRANSLATE_MERIDIEM
- * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS
- *
- * @return string
- */
- public static function translateTimeString($timeString, $from = null, $to = null, $mode = 15);
-
- /**
- * Translate a time string from the current locale (`$date->locale()`) to an other.
- *
- * @param string $timeString time string to translate
- * @param string|null $to output locale of the result returned ("en" by default)
- *
- * @return string
- */
- public function translateTimeStringTo($timeString, $to = null);
-
- /**
- * Translate using translation string or callback available.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- * @param string $key
- * @param array $parameters
- * @param null $number
- *
- * @return string
- */
- public static function translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string;
-
- /**
- * Format as ->format() do (using date replacements patterns from http://php.net/manual/fr/function.date.php)
- * but translate words whenever possible (months, day names, etc.) using the current locale.
- *
- * @param string $format
- *
- * @return string
- */
- public function translatedFormat(string $format): string;
-
- /**
- * Set the timezone or returns the timezone name if no arguments passed.
- *
- * @param \DateTimeZone|string $value
- *
- * @return CarbonInterface|string
- */
- public function tz($value = null);
-
- /**
- * @alias getTimestamp
- *
- * Returns the UNIX timestamp for the current date.
- *
- * @return int
- */
- public function unix();
-
- /**
- * @alias to
- *
- * Get the difference in a human readable format in the current locale from an other
- * instance given (or now if null given) to current instance.
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Indicates if months should be calculated with overflow.
- *
- * @param bool $monthsOverflow
- *
- * @return void
- */
- public static function useMonthsOverflow($monthsOverflow = true);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * Enable the strict mode (or disable with passing false).
- *
- * @param bool $strictModeEnabled
- */
- public static function useStrictMode($strictModeEnabled = true);
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Indicates if years should be calculated with overflow.
- *
- * @param bool $yearsOverflow
- *
- * @return void
- */
- public static function useYearsOverflow($yearsOverflow = true);
-
- /**
- * Set the instance's timezone to UTC.
- *
- * @return static|CarbonInterface
- */
- public function utc();
-
- /**
- * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed.
- *
- * @param int|null $offset
- *
- * @return int|static|CarbonInterface
- */
- public function utcOffset(int $offset = null);
-
- /**
- * Returns the milliseconds timestamps used amongst other by Date javascript objects.
- *
- * @return float
- */
- public function valueOf();
-
- /**
- * Get/set the week number using given first day of week and first
- * day of year included in the first week. Or use US format if no settings
- * given (Sunday / Jan 6).
- *
- * @param int|null $week
- * @param int|null $dayOfWeek
- * @param int|null $dayOfYear
- *
- * @return int|static
- */
- public function week($week = null, $dayOfWeek = null, $dayOfYear = null);
-
- /**
- * Set/get the week number of year using given first day of week and first
- * day of year included in the first week. Or use US format if no settings
- * given (Sunday / Jan 6).
- *
- * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int|static|CarbonInterface
- */
- public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null);
-
- /**
- * Get/set the weekday from 0 (Sunday) to 6 (Saturday).
- *
- * @param int|null $value new value for weekday if using as setter.
- *
- * @return static|CarbonInterface|int
- */
- public function weekday($value = null);
-
- /**
- * Get the number of weeks of the current week-year using given first day of week and first
- * day of year included in the first week. Or use US format if no settings
- * given (Sunday / Jan 6).
- *
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int
- */
- public function weeksInYear($dayOfWeek = null, $dayOfYear = null);
-
- /**
- * Create a Carbon instance for yesterday.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function yesterday($tz = null);
-
- // </methods>
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use BadMethodCallException;
-use Carbon\Traits\Options;
-use Closure;
-use DateInterval;
-use InvalidArgumentException;
-use ReflectionClass;
-use ReflectionMethod;
-
-/**
- * A simple API extension for DateInterval.
- * The implementation provides helpers to handle weeks but only days are saved.
- * Weeks are calculated based on the total days of the current instance.
- *
- * @property int $years Total years of the current interval.
- * @property int $months Total months of the current interval.
- * @property int $weeks Total weeks of the current interval calculated from the days.
- * @property int $dayz Total days of the current interval (weeks * 7 + days).
- * @property int $hours Total hours of the current interval.
- * @property int $minutes Total minutes of the current interval.
- * @property int $seconds Total seconds of the current interval.
- * @property int $microseconds Total microseconds of the current interval.
- * @property int $milliseconds Total microseconds of the current interval.
- * @property-read int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
- * @property-read int $daysExcludeWeeks alias of dayzExcludeWeeks
- * @property-read float $totalYears Number of years equivalent to the interval.
- * @property-read float $totalMonths Number of months equivalent to the interval.
- * @property-read float $totalWeeks Number of weeks equivalent to the interval.
- * @property-read float $totalDays Number of days equivalent to the interval.
- * @property-read float $totalDayz Alias for totalDays.
- * @property-read float $totalHours Number of hours equivalent to the interval.
- * @property-read float $totalMinutes Number of minutes equivalent to the interval.
- * @property-read float $totalSeconds Number of seconds equivalent to the interval.
- * @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval.
- * @property-read float $totalMicroseconds Number of microseconds equivalent to the interval.
- * @property-read string $locale locale of the current instance
- *
- * @method static CarbonInterval years($years = 1) Create instance specifying a number of years.
- * @method static CarbonInterval year($years = 1) Alias for years()
- * @method static CarbonInterval months($months = 1) Create instance specifying a number of months.
- * @method static CarbonInterval month($months = 1) Alias for months()
- * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks.
- * @method static CarbonInterval week($weeks = 1) Alias for weeks()
- * @method static CarbonInterval days($days = 1) Create instance specifying a number of days.
- * @method static CarbonInterval dayz($days = 1) Alias for days()
- * @method static CarbonInterval day($days = 1) Alias for days()
- * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours.
- * @method static CarbonInterval hour($hours = 1) Alias for hours()
- * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes.
- * @method static CarbonInterval minute($minutes = 1) Alias for minutes()
- * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds.
- * @method static CarbonInterval second($seconds = 1) Alias for seconds()
- * @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds.
- * @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds()
- * @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds.
- * @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds()
- * @method CarbonInterval years($years = 1) Set the years portion of the current interval.
- * @method CarbonInterval year($years = 1) Alias for years().
- * @method CarbonInterval months($months = 1) Set the months portion of the current interval.
- * @method CarbonInterval month($months = 1) Alias for months().
- * @method CarbonInterval weeks($weeks = 1) Set the weeks portion of the current interval. Will overwrite dayz value.
- * @method CarbonInterval week($weeks = 1) Alias for weeks().
- * @method CarbonInterval days($days = 1) Set the days portion of the current interval.
- * @method CarbonInterval dayz($days = 1) Alias for days().
- * @method CarbonInterval day($days = 1) Alias for days().
- * @method CarbonInterval hours($hours = 1) Set the hours portion of the current interval.
- * @method CarbonInterval hour($hours = 1) Alias for hours().
- * @method CarbonInterval minutes($minutes = 1) Set the minutes portion of the current interval.
- * @method CarbonInterval minute($minutes = 1) Alias for minutes().
- * @method CarbonInterval seconds($seconds = 1) Set the seconds portion of the current interval.
- * @method CarbonInterval second($seconds = 1) Alias for seconds().
- * @method CarbonInterval milliseconds($seconds = 1) Set the seconds portion of the current interval.
- * @method CarbonInterval millisecond($seconds = 1) Alias for seconds().
- * @method CarbonInterval microseconds($seconds = 1) Set the seconds portion of the current interval.
- * @method CarbonInterval microsecond($seconds = 1) Alias for seconds().
- */
-class CarbonInterval extends DateInterval
-{
- use Options;
-
- /**
- * Interval spec period designators
- */
- const PERIOD_PREFIX = 'P';
- const PERIOD_YEARS = 'Y';
- const PERIOD_MONTHS = 'M';
- const PERIOD_DAYS = 'D';
- const PERIOD_TIME_PREFIX = 'T';
- const PERIOD_HOURS = 'H';
- const PERIOD_MINUTES = 'M';
- const PERIOD_SECONDS = 'S';
-
- /**
- * A translator to ... er ... translate stuff
- *
- * @var \Symfony\Component\Translation\TranslatorInterface
- */
- protected static $translator;
-
- /**
- * @var array|null
- */
- protected static $cascadeFactors;
-
- /**
- * @var array|null
- */
- private static $flipCascadeFactors;
-
- /**
- * The registered macros.
- *
- * @var array
- */
- protected static $macros = [];
-
- /**
- * Timezone handler for settings() method.
- *
- * @var mixed
- */
- protected $tzName;
-
- public function shiftTimezone($tzName)
- {
- $this->tzName = $tzName;
-
- return $this;
- }
-
- /**
- * Mapping of units and factors for cascading.
- *
- * Should only be modified by changing the factors or referenced constants.
- *
- * @return array
- */
- public static function getCascadeFactors()
- {
- return static::$cascadeFactors ?: [
- 'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
- 'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
- 'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
- 'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
- 'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
- 'months' => [Carbon::DAYS_PER_WEEK * Carbon::WEEKS_PER_MONTH, 'dayz'],
- 'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
- ];
- }
-
- private static function standardizeUnit($unit)
- {
- $unit = rtrim($unit, 'sz').'s';
-
- return $unit === 'days' ? 'dayz' : $unit;
- }
-
- private static function getFlipCascadeFactors()
- {
- if (!self::$flipCascadeFactors) {
- self::$flipCascadeFactors = [];
- foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
- self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
- }
- }
-
- return self::$flipCascadeFactors;
- }
-
- /**
- * Set default cascading factors for ->cascade() method.
- *
- * @param array $cascadeFactors
- */
- public static function setCascadeFactors(array $cascadeFactors)
- {
- self::$flipCascadeFactors = null;
- static::$cascadeFactors = $cascadeFactors;
- }
-
- ///////////////////////////////////////////////////////////////////
- //////////////////////////// CONSTRUCTORS /////////////////////////
- ///////////////////////////////////////////////////////////////////
-
- /**
- * Create a new CarbonInterval instance.
- *
- * @param int $years
- * @param int $months
- * @param int $weeks
- * @param int $days
- * @param int $hours
- * @param int $minutes
- * @param int $seconds
- * @param int $microseconds
- *
- * @throws \Exception
- */
- public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
- {
- $spec = $years;
-
- if (!is_string($spec) || floatval($years) || preg_match('/^[0-9.]/', $years)) {
- $spec = static::PERIOD_PREFIX;
-
- $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
- $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
-
- $specDays = 0;
- $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
- $specDays += $days > 0 ? $days : 0;
-
- $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
-
- if ($hours > 0 || $minutes > 0 || $seconds > 0) {
- $spec .= static::PERIOD_TIME_PREFIX;
- $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
- $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
- $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
- }
-
- if ($spec === static::PERIOD_PREFIX) {
- // Allow the zero interval.
- $spec .= '0'.static::PERIOD_YEARS;
- }
- }
-
- parent::__construct($spec);
-
- if (!is_null($microseconds)) {
- $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
- }
- }
-
- /**
- * Returns the factor for a given source-to-target couple.
- *
- * @param string $source
- * @param string $target
- *
- * @return int|null
- */
- public static function getFactor($source, $target)
- {
- $source = self::standardizeUnit($source);
- $target = self::standardizeUnit($target);
- $factors = static::getFlipCascadeFactors();
- if (isset($factors[$source])) {
- [$to, $factor] = $factors[$source];
- if ($to === $target) {
- return $factor;
- }
- }
-
- return null;
- }
-
- /**
- * Returns current config for days per week.
- *
- * @return int
- */
- public static function getDaysPerWeek()
- {
- return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
- }
-
- /**
- * Returns current config for hours per day.
- *
- * @return int
- */
- public static function getHoursPerDay()
- {
- return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
- }
-
- /**
- * Returns current config for minutes per hour.
- *
- * @return int
- */
- public static function getMinutesPerHour()
- {
- return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
- }
-
- /**
- * Returns current config for seconds per minute.
- *
- * @return int
- */
- public static function getSecondsPerMinute()
- {
- return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
- }
-
- /**
- * Returns current config for microseconds per second.
- *
- * @return int
- */
- public static function getMillisecondsPerSecond()
- {
- return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
- }
-
- /**
- * Returns current config for microseconds per second.
- *
- * @return int
- */
- public static function getMicrosecondsPerMillisecond()
- {
- return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
- }
-
- /**
- * Create a new CarbonInterval instance from specific values.
- * This is an alias for the constructor that allows better fluent
- * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
- * (new CarbonInterval(1))->fn().
- *
- * @param int $years
- * @param int $months
- * @param int $weeks
- * @param int $days
- * @param int $hours
- * @param int $minutes
- * @param int $seconds
- * @param int $microseconds
- *
- * @return static
- */
- public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
- {
- return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
- }
-
- /**
- * Get a copy of the instance.
- *
- * @return static
- */
- public function copy()
- {
- $date = new static($this->spec());
- $date->invert = $this->invert;
-
- return $date;
- }
-
- /**
- * Provide static helpers to create instances. Allows CarbonInterval::years(3).
- *
- * Note: This is done using the magic method to allow static and instance methods to
- * have the same names.
- *
- * @param string $method magic method name called
- * @param array $parameters parameters list
- *
- * @return static|null
- */
- public static function __callStatic($method, $parameters)
- {
- $arg = count($parameters) === 0 ? 1 : $parameters[0];
-
- switch (Carbon::singularUnit(rtrim($method, 'z'))) {
- case 'year':
- return new static($arg);
-
- case 'month':
- return new static(null, $arg);
-
- case 'week':
- return new static(null, null, $arg);
-
- case 'day':
- return new static(null, null, null, $arg);
-
- case 'hour':
- return new static(null, null, null, null, $arg);
-
- case 'minute':
- return new static(null, null, null, null, null, $arg);
-
- case 'second':
- return new static(null, null, null, null, null, null, $arg);
-
- case 'millisecond':
- case 'milli':
- return new static(null, null, null, null, null, null, null, $arg * Carbon::MICROSECONDS_PER_MILLISECOND);
-
- case 'microsecond':
- case 'micro':
- return new static(null, null, null, null, null, null, null, $arg);
- }
-
- if (static::hasMacro($method)) {
- return (new static(0))->$method(...$parameters);
- }
-
- if (Carbon::isStrictModeEnabled()) {
- throw new BadMethodCallException(sprintf("Unknown fluent constructor '%s'.", $method));
- }
-
- return null;
- }
-
- /**
- * Creates a CarbonInterval from string.
- *
- * Format:
- *
- * Suffix | Unit | Example | DateInterval expression
- * -------|---------|---------|------------------------
- * y | years | 1y | P1Y
- * mo | months | 3mo | P3M
- * w | weeks | 2w | P2W
- * d | days | 28d | P28D
- * h | hours | 4h | PT4H
- * m | minutes | 12m | PT12M
- * s | seconds | 59s | PT59S
- *
- * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
- *
- * Special cases:
- * - An empty string will return a zero interval
- * - Fractions are allowed for weeks, days, hours and minutes and will be converted
- * and rounded to the next smaller value (caution: 0.5w = 4d)
- *
- * @param string $intervalDefinition
- *
- * @return static
- */
- public static function fromString($intervalDefinition)
- {
- if (empty($intervalDefinition)) {
- return new static(0);
- }
-
- $years = 0;
- $months = 0;
- $weeks = 0;
- $days = 0;
- $hours = 0;
- $minutes = 0;
- $seconds = 0;
- $milliseconds = 0;
- $microseconds = 0;
-
- $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
- preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
- while ([$part, $value, $unit] = array_shift($parts)) {
- $intValue = intval($value);
- $fraction = floatval($value) - $intValue;
- // Fix calculation precision
- switch (round($fraction, 6)) {
- case 1:
- $fraction = 0;
- $intValue++;
- break;
- case 0:
- $fraction = 0;
- break;
- }
- switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
- case 'year':
- case 'years':
- case 'y':
- $years += $intValue;
- break;
-
- case 'month':
- case 'months':
- case 'mo':
- $months += $intValue;
- break;
-
- case 'week':
- case 'weeks':
- case 'w':
- $weeks += $intValue;
- if ($fraction) {
- $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
- }
- break;
-
- case 'day':
- case 'days':
- case 'd':
- $days += $intValue;
- if ($fraction) {
- $parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
- }
- break;
-
- case 'hour':
- case 'hours':
- case 'h':
- $hours += $intValue;
- if ($fraction) {
- $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
- }
- break;
-
- case 'minute':
- case 'minutes':
- case 'm':
- $minutes += $intValue;
- if ($fraction) {
- $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
- }
- break;
-
- case 'second':
- case 'seconds':
- case 's':
- $seconds += $intValue;
- if ($fraction) {
- $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
- }
- break;
-
- case 'millisecond':
- case 'milliseconds':
- case 'milli':
- case 'ms':
- $milliseconds += $intValue;
- if ($fraction) {
- $microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
- }
- break;
-
- case 'microsecond':
- case 'microseconds':
- case 'micro':
- case 'µs':
- $microseconds += $intValue;
- break;
-
- default:
- throw new InvalidArgumentException(
- sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
- );
- }
- }
-
- return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
- }
-
- /**
- * Create a CarbonInterval instance from a DateInterval one. Can not instance
- * DateInterval objects created from DateTime::diff() as you can't externally
- * set the $days field.
- *
- * @param DateInterval $di
- *
- * @return static
- */
- public static function instance(DateInterval $di)
- {
- $microseconds = $di->f;
- $instance = new static(static::getDateIntervalSpec($di));
- if ($microseconds) {
- $instance->f = $microseconds;
- }
- $instance->invert = $di->invert;
- foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
- if ($di->$unit < 0) {
- $instance->$unit *= -1;
- }
- }
-
- return $instance;
- }
-
- /**
- * Make a CarbonInterval instance from given variable if possible.
- *
- * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
- * and recurrences). Throw an exception for invalid format, but otherwise return null.
- *
- * @param mixed $var
- *
- * @return static|null
- */
- public static function make($var)
- {
- if ($var instanceof DateInterval) {
- return static::instance($var);
- }
-
- if (!is_string($var)) {
- return null;
- }
-
- $var = trim($var);
-
- if (preg_match('/^P[T0-9]/', $var)) {
- return new static($var);
- }
-
- if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $var)) {
- return static::fromString($var);
- }
-
- /** @var static $interval */
- $interval = static::createFromDateString($var);
-
- return $interval->isEmpty() ? null : $interval;
- }
-
- /**
- * Sets up a DateInterval from the relative parts of the string.
- *
- * @param string $time
- *
- * @return static
- *
- * @link http://php.net/manual/en/dateinterval.createfromdatestring.php
- */
- public static function createFromDateString($time)
- {
- $interval = parent::createFromDateString($time);
- if ($interval instanceof DateInterval && !($interval instanceof static)) {
- $interval = static::instance($interval);
- }
-
- return static::instance($interval);
- }
-
- ///////////////////////////////////////////////////////////////////
- ///////////////////////// GETTERS AND SETTERS /////////////////////
- ///////////////////////////////////////////////////////////////////
-
- /**
- * Get a part of the CarbonInterval object.
- *
- * @param string $name
- *
- * @throws \InvalidArgumentException
- *
- * @return int|float|string
- */
- public function __get($name)
- {
- if (substr($name, 0, 5) === 'total') {
- return $this->total(substr($name, 5));
- }
-
- switch ($name) {
- case 'years':
- return $this->y;
-
- case 'months':
- return $this->m;
-
- case 'dayz':
- return $this->d;
-
- case 'hours':
- return $this->h;
-
- case 'minutes':
- return $this->i;
-
- case 'seconds':
- return $this->s;
-
- case 'milli':
- case 'milliseconds':
- return (int) floor(round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
-
- case 'micro':
- case 'microseconds':
- return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
-
- case 'weeks':
- return (int) floor($this->d / static::getDaysPerWeek());
-
- case 'daysExcludeWeeks':
- case 'dayzExcludeWeeks':
- return $this->d % static::getDaysPerWeek();
-
- case 'locale':
- return $this->getLocalTranslator()->getLocale();
-
- default:
- throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
- }
- }
-
- /**
- * Set a part of the CarbonInterval object.
- *
- * @param string $name
- * @param int $value
- *
- * @throws \InvalidArgumentException
- */
- public function __set($name, $value)
- {
- switch (Carbon::singularUnit(rtrim($name, 'z'))) {
- case 'year':
- $this->y = $value;
- break;
-
- case 'month':
- $this->m = $value;
- break;
-
- case 'week':
- $this->d = $value * static::getDaysPerWeek();
- break;
-
- case 'day':
- $this->d = $value;
- break;
-
- case 'hour':
- $this->h = $value;
- break;
-
- case 'minute':
- $this->i = $value;
- break;
-
- case 'second':
- $this->s = $value;
- break;
-
- case 'milli':
- case 'millisecond':
- $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
- break;
-
- case 'micro':
- case 'microsecond':
- $this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
- break;
-
- default:
- if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
- throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
- }
-
- $this->$name = $value;
- }
- }
-
- /**
- * Allow setting of weeks and days to be cumulative.
- *
- * @param int $weeks Number of weeks to set
- * @param int $days Number of days to set
- *
- * @return static
- */
- public function weeksAndDays($weeks, $days)
- {
- $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
-
- return $this;
- }
-
- /**
- * Returns true if the interval is empty for each unit.
- *
- * @return bool
- */
- public function isEmpty()
- {
- return $this->years === 0 &&
- $this->months === 0 &&
- $this->dayz === 0 &&
- !$this->days &&
- $this->hours === 0 &&
- $this->minutes === 0 &&
- $this->seconds === 0 &&
- $this->microseconds === 0;
- }
-
- /**
- * Register a custom macro.
- *
- * @example
- * ```
- * CarbonInterval::macro('twice', function () {
- * return $this->times(2);
- * });
- * echo CarbonInterval::hours(2)->twice();
- * ```
- *
- * @param string $name
- * @param object|callable $macro
- *
- * @return void
- */
- public static function macro($name, $macro)
- {
- static::$macros[$name] = $macro;
- }
-
- /**
- * Register macros from a mixin object.
- *
- * @example
- * ```
- * CarbonInterval::mixin(new class {
- * public function daysToHours() {
- * return function () {
- * $this->hours += $this->days;
- * $this->days = 0;
- *
- * return $this;
- * };
- * }
- * public function hoursToDays() {
- * return function () {
- * $this->days += $this->hours;
- * $this->hours = 0;
- *
- * return $this;
- * };
- * }
- * });
- * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
- * echo CarbonInterval::days(5)->daysToHours() . "\n";
- * ```
- *
- * @param object $mixin
- *
- * @throws \ReflectionException
- *
- * @return void
- */
- public static function mixin($mixin)
- {
- $reflection = new ReflectionClass($mixin);
-
- $methods = $reflection->getMethods(
- ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
- );
-
- foreach ($methods as $method) {
- $method->setAccessible(true);
-
- static::macro($method->name, $method->invoke($mixin));
- }
- }
-
- /**
- * Check if macro is registered.
- *
- * @param string $name
- *
- * @return bool
- */
- public static function hasMacro($name)
- {
- return isset(static::$macros[$name]);
- }
-
- /**
- * Call given macro.
- *
- * @param string $name
- * @param array $parameters
- *
- * @return mixed
- */
- protected function callMacro($name, $parameters)
- {
- $macro = static::$macros[$name];
-
- if ($macro instanceof Closure) {
- return call_user_func_array($macro->bindTo($this, static::class), $parameters);
- }
-
- return call_user_func_array($macro, $parameters);
- }
-
- /**
- * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
- *
- * Note: This is done using the magic method to allow static and instance methods to
- * have the same names.
- *
- * @param string $method magic method name called
- * @param array $parameters parameters list
- *
- * @return static
- */
- public function __call($method, $parameters)
- {
- if (static::hasMacro($method)) {
- return $this->callMacro($method, $parameters);
- }
-
- $arg = count($parameters) === 0 ? 1 : $parameters[0];
-
- switch (Carbon::singularUnit(rtrim($method, 'z'))) {
- case 'year':
- $this->years = $arg;
- break;
-
- case 'month':
- $this->months = $arg;
- break;
-
- case 'week':
- $this->dayz = $arg * static::getDaysPerWeek();
- break;
-
- case 'day':
- $this->dayz = $arg;
- break;
-
- case 'hour':
- $this->hours = $arg;
- break;
-
- case 'minute':
- $this->minutes = $arg;
- break;
-
- case 'second':
- $this->seconds = $arg;
- break;
-
- case 'milli':
- case 'millisecond':
- $this->milliseconds = $arg;
- break;
-
- case 'micro':
- case 'microsecond':
- $this->microseconds = $arg;
- break;
-
- default:
- if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
- throw new BadMethodCallException(sprintf("Unknown fluent setter '%s'", $method));
- }
- }
-
- return $this;
- }
-
- protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
- {
- $join = ' ';
- $aUnit = false;
- if (is_array($syntax)) {
- extract($syntax);
- } else {
- if (is_int($short)) {
- $parts = $short;
- $short = false;
- }
- if (is_bool($syntax)) {
- $short = $syntax;
- $syntax = CarbonInterface::DIFF_ABSOLUTE;
- }
- }
- if (is_null($syntax)) {
- $syntax = CarbonInterface::DIFF_ABSOLUTE;
- }
- if ($parts === -1) {
- $parts = INF;
- }
- if (is_null($options)) {
- $options = static::getHumanDiffOptions();
- }
- if ($join === true) {
- $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
- $join = [
- $default,
- $this->getTranslationMessage('list.1') ?? $default,
- ];
- }
- if (is_array($join)) {
- [$default, $last] = $join;
-
- $join = function ($list) use ($default, $last) {
- if (count($list) < 2) {
- return implode('', $list);
- }
-
- $end = array_pop($list);
-
- return implode($default, $list).$last.$end;
- };
- }
- if (is_string($join)) {
- $glue = $join;
- $join = function ($list) use ($glue) {
- return implode($glue, $list);
- };
- }
-
- return [$syntax, $short, $parts, $options, $join, $aUnit];
- }
-
- /**
- * Get the current interval in a human readable format in the current locale.
- *
- * @example
- * ```
- * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
- * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
- * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
- * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
- * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
- * ```
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'aUnit' entry, prefer "an hour" over "1 hour" if true
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: -1: no limits)
- * @param int $options human diff options
- *
- * @return string
- */
- public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
- {
- [$syntax, $short, $parts, $options, $join, $aUnit] = $this->getForHumansParameters($syntax, $short, $parts, $options);
-
- $interval = [];
- $syntax = (int) ($syntax === null ? CarbonInterface::DIFF_ABSOLUTE : $syntax);
- $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
- $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
- $count = 1;
- $unit = $short ? 's' : 'second';
-
- /** @var \Symfony\Component\Translation\Translator $translator */
- $translator = $this->getLocalTranslator();
-
- $diffIntervalArray = [
- ['value' => $this->years, 'unit' => 'year', 'unitShort' => 'y'],
- ['value' => $this->months, 'unit' => 'month', 'unitShort' => 'm'],
- ['value' => $this->weeks, 'unit' => 'week', 'unitShort' => 'w'],
- ['value' => $this->daysExcludeWeeks, 'unit' => 'day', 'unitShort' => 'd'],
- ['value' => $this->hours, 'unit' => 'hour', 'unitShort' => 'h'],
- ['value' => $this->minutes, 'unit' => 'minute', 'unitShort' => 'min'],
- ['value' => $this->seconds, 'unit' => 'second', 'unitShort' => 's'],
- ];
-
- $transChoice = function ($short, $unitData) use ($translator, $aUnit) {
- $count = $unitData['value'];
-
- if ($short) {
- $result = $this->translate($unitData['unitShort'], [], $count, $translator);
-
- if ($result !== $unitData['unitShort']) {
- return $result;
- }
- } elseif ($aUnit) {
- $key = 'a_'.$unitData['unit'];
- $result = $this->translate($key, [], $count, $translator);
-
- if ($result !== $key) {
- return $result;
- }
- }
-
- return $this->translate($unitData['unit'], [], $count, $translator);
- };
-
- foreach ($diffIntervalArray as $diffIntervalData) {
- if ($diffIntervalData['value'] > 0) {
- $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
- $count = $diffIntervalData['value'];
- $interval[] = $transChoice($short, $diffIntervalData);
- } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && count($interval) > 0) {
- break;
- }
-
- // break the loop after we get the required number of parts in array
- if (count($interval) >= $parts) {
- break;
- }
- }
-
- if (count($interval) === 0) {
- if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
- $key = 'diff_now';
- $translation = $this->translate($key, [], null, $translator);
- if ($translation !== $key) {
- return $translation;
- }
- }
- $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
- $unit = $short ? 's' : 'second';
- $interval[] = $this->translate($unit, [], $count, $translator);
- }
-
- // join the interval parts by a space
- $time = $join($interval);
-
- unset($diffIntervalArray, $interval);
-
- if ($absolute) {
- return $time;
- }
-
- $isFuture = $this->invert === 1;
-
- $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
-
- if ($parts === 1) {
- if ($relativeToNow && $unit === 'day') {
- if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
- $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
- $translation = $this->translate($key, [], null, $translator);
- if ($translation !== $key) {
- return $translation;
- }
- }
- if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
- $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
- $translation = $this->translate($key, [], null, $translator);
- if ($translation !== $key) {
- return $translation;
- }
- }
- }
- // Some languages have special pluralization for past and future tense.
- $key = $unit.'_'.$transId;
- if ($key !== $this->translate($key, [], null, $translator)) {
- $time = $this->translate($key, [], $count, $translator);
- }
- }
-
- return $this->translate($transId, [':time' => $time], null, $translator);
- }
-
- /**
- * Format the instance as a string using the forHumans() function.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->forHumans();
- }
-
- /**
- * Convert the interval to a CarbonPeriod.
- *
- * @return CarbonPeriod
- */
- public function toPeriod(...$params)
- {
- return CarbonPeriod::create($this, ...$params);
- }
-
- /**
- * Invert the interval.
- *
- * @return $this
- */
- public function invert()
- {
- $this->invert = $this->invert ? 0 : 1;
-
- return $this;
- }
-
- protected function solveNegativeInterval()
- {
- if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
- $this->years *= -1;
- $this->months *= -1;
- $this->dayz *= -1;
- $this->hours *= -1;
- $this->minutes *= -1;
- $this->seconds *= -1;
- $this->microseconds *= -1;
- $this->invert();
- }
-
- return $this;
- }
-
- /**
- * Add the passed interval to the current instance.
- *
- * @param string|DateInterval $unit
- * @param int $value
- *
- * @return static
- */
- public function add($unit, $value = 1)
- {
- if (is_numeric($unit)) {
- $_unit = $value;
- $value = $unit;
- $unit = $_unit;
- unset($_unit);
- }
-
- if (is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
- $unit = "$value $unit";
- $value = 1;
- }
-
- $interval = static::make($unit);
-
- if (!$interval) {
- throw new InvalidArgumentException('This type of data cannot be added/subtracted.');
- }
-
- if ($value !== 1) {
- $interval->times($value);
- }
- $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
- $this->years += $interval->y * $sign;
- $this->months += $interval->m * $sign;
- $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
- $this->hours += $interval->h * $sign;
- $this->minutes += $interval->i * $sign;
- $this->seconds += $interval->s * $sign;
- $this->microseconds += $interval->microseconds * $sign;
-
- $this->solveNegativeInterval();
-
- return $this;
- }
-
- /**
- * Subtract the passed interval to the current instance.
- *
- * @param string|DateInterval $unit
- * @param int $value
- *
- * @return static
- */
- public function sub($unit, $value = 1)
- {
- if (is_numeric($unit)) {
- $_unit = $value;
- $value = $unit;
- $unit = $_unit;
- unset($_unit);
- }
-
- return $this->add($unit, -floatval($value));
- }
-
- /**
- * Subtract the passed interval to the current instance.
- *
- * @param string|DateInterval $unit
- * @param int $value
- *
- * @return static
- */
- public function subtract($unit, $value = 1)
- {
- return $this->sub($unit, $value);
- }
-
- /**
- * Multiply current instance given number of times
- *
- * @param float|int $factor
- *
- * @return $this
- */
- public function times($factor)
- {
- if ($factor < 0) {
- $this->invert = $this->invert ? 0 : 1;
- $factor = -$factor;
- }
-
- $this->years = (int) round($this->years * $factor);
- $this->months = (int) round($this->months * $factor);
- $this->dayz = (int) round($this->dayz * $factor);
- $this->hours = (int) round($this->hours * $factor);
- $this->minutes = (int) round($this->minutes * $factor);
- $this->seconds = (int) round($this->seconds * $factor);
- $this->microseconds = (int) round($this->microseconds * $factor);
-
- return $this;
- }
-
- /**
- * Get the interval_spec string of a date interval.
- *
- * @param DateInterval $interval
- *
- * @return string
- */
- public static function getDateIntervalSpec(DateInterval $interval)
- {
- $date = array_filter([
- static::PERIOD_YEARS => abs($interval->y),
- static::PERIOD_MONTHS => abs($interval->m),
- static::PERIOD_DAYS => abs($interval->d),
- ]);
-
- $time = array_filter([
- static::PERIOD_HOURS => abs($interval->h),
- static::PERIOD_MINUTES => abs($interval->i),
- static::PERIOD_SECONDS => abs($interval->s),
- ]);
-
- $specString = static::PERIOD_PREFIX;
-
- foreach ($date as $key => $value) {
- $specString .= $value.$key;
- }
-
- if (count($time) > 0) {
- $specString .= static::PERIOD_TIME_PREFIX;
- foreach ($time as $key => $value) {
- $specString .= $value.$key;
- }
- }
-
- return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
- }
-
- /**
- * Get the interval_spec string.
- *
- * @return string
- */
- public function spec()
- {
- return static::getDateIntervalSpec($this);
- }
-
- /**
- * Comparing 2 date intervals.
- *
- * @param DateInterval $a
- * @param DateInterval $b
- *
- * @return int
- */
- public static function compareDateIntervals(DateInterval $a, DateInterval $b)
- {
- $current = Carbon::now();
- $passed = $current->copy()->add($b);
- $current->add($a);
-
- if ($current < $passed) {
- return -1;
- }
- if ($current > $passed) {
- return 1;
- }
-
- return 0;
- }
-
- /**
- * Comparing with passed interval.
- *
- * @param DateInterval $interval
- *
- * @return int
- */
- public function compare(DateInterval $interval)
- {
- return static::compareDateIntervals($this, $interval);
- }
-
- /**
- * Convert overflowed values into bigger units.
- *
- * @return $this
- */
- public function cascade()
- {
- foreach (static::getFlipCascadeFactors() as $source => [$target, $factor]) {
- if ($source === 'dayz' && $target === 'weeks') {
- continue;
- }
-
- $value = $this->$source;
- $this->$source = $modulo = ($factor + ($value % $factor)) % $factor;
- $this->$target += ($value - $modulo) / $factor;
- if ($this->$source > 0 && $this->$target < 0) {
- $this->$source -= $factor;
- $this->$target++;
- }
- }
-
- return $this->solveNegativeInterval();
- }
-
- /**
- * Get amount of given unit equivalent to the interval.
- *
- * @param string $unit
- *
- * @throws \InvalidArgumentException
- *
- * @return float
- */
- public function total($unit)
- {
- $realUnit = $unit = strtolower($unit);
-
- if (in_array($unit, ['days', 'weeks'])) {
- $realUnit = 'dayz';
- } elseif (!in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
- throw new InvalidArgumentException("Unknown unit '$unit'.");
- }
-
- $result = 0;
- $cumulativeFactor = 0;
- $unitFound = false;
- $factors = static::getFlipCascadeFactors();
-
- foreach ($factors as $source => [$target, $factor]) {
- if ($source === $realUnit) {
- $unitFound = true;
- $value = $this->$source;
- if ($source === 'microseconds' && isset($factors['milliseconds'])) {
- $value %= Carbon::MICROSECONDS_PER_MILLISECOND;
- }
- $result += $value;
- $cumulativeFactor = 1;
- }
-
- if ($factor === false) {
- if ($unitFound) {
- break;
- }
-
- $result = 0;
- $cumulativeFactor = 0;
-
- continue;
- }
-
- if ($target === $realUnit) {
- $unitFound = true;
- }
-
- if ($cumulativeFactor) {
- $cumulativeFactor *= $factor;
- $result += $this->$target * $cumulativeFactor;
-
- continue;
- }
-
- $value = $this->$source;
-
- if ($source === 'microseconds' && isset($factors['milliseconds'])) {
- $value %= Carbon::MICROSECONDS_PER_MILLISECOND;
- }
-
- $result = ($result + $value) / $factor;
- }
-
- if (isset($target) && !$cumulativeFactor) {
- $result += $this->$target;
- }
-
- if (!$unitFound) {
- throw new \InvalidArgumentException("Unit $unit have no configuration to get total from other units.");
- }
-
- if ($unit === 'weeks') {
- return $result / static::getDaysPerWeek();
- }
-
- return $result;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use BadMethodCallException;
-use Carbon\Traits\Options;
-use Closure;
-use Countable;
-use DateInterval;
-use DateTime;
-use DateTimeInterface;
-use InvalidArgumentException;
-use Iterator;
-use ReflectionClass;
-use ReflectionMethod;
-use RuntimeException;
-
-/**
- * Substitution of DatePeriod with some modifications and many more features.
- *
- * @method static CarbonPeriod start($date, $inclusive = null) Create instance specifying start date.
- * @method static CarbonPeriod since($date, $inclusive = null) Alias for start().
- * @method static CarbonPeriod sinceNow($inclusive = null) Create instance with start date set to now.
- * @method static CarbonPeriod end($date = null, $inclusive = null) Create instance specifying end date.
- * @method static CarbonPeriod until($date = null, $inclusive = null) Alias for end().
- * @method static CarbonPeriod untilNow($inclusive = null) Create instance with end date set to now.
- * @method static CarbonPeriod dates($start, $end = null) Create instance with start and end date.
- * @method static CarbonPeriod between($start, $end = null) Create instance with start and end date.
- * @method static CarbonPeriod recurrences($recurrences = null) Create instance with maximum number of recurrences.
- * @method static CarbonPeriod times($recurrences = null) Alias for recurrences().
- * @method static CarbonPeriod options($options = null) Create instance with options.
- * @method static CarbonPeriod toggle($options, $state = null) Create instance with options toggled on or off.
- * @method static CarbonPeriod filter($callback, $name = null) Create instance with filter added to the stack.
- * @method static CarbonPeriod push($callback, $name = null) Alias for filter().
- * @method static CarbonPeriod prepend($callback, $name = null) Create instance with filter prepened to the stack.
- * @method static CarbonPeriod filters(array $filters) Create instance with filters stack.
- * @method static CarbonPeriod interval($interval) Create instance with given date interval.
- * @method static CarbonPeriod each($interval) Create instance with given date interval.
- * @method static CarbonPeriod every($interval) Create instance with given date interval.
- * @method static CarbonPeriod step($interval) Create instance with given date interval.
- * @method static CarbonPeriod stepBy($interval) Create instance with given date interval.
- * @method static CarbonPeriod invert() Create instance with inverted date interval.
- * @method static CarbonPeriod years($years = 1) Create instance specifying a number of years for date interval.
- * @method static CarbonPeriod year($years = 1) Alias for years().
- * @method static CarbonPeriod months($months = 1) Create instance specifying a number of months for date interval.
- * @method static CarbonPeriod month($months = 1) Alias for months().
- * @method static CarbonPeriod weeks($weeks = 1) Create instance specifying a number of weeks for date interval.
- * @method static CarbonPeriod week($weeks = 1) Alias for weeks().
- * @method static CarbonPeriod days($days = 1) Create instance specifying a number of days for date interval.
- * @method static CarbonPeriod dayz($days = 1) Alias for days().
- * @method static CarbonPeriod day($days = 1) Alias for days().
- * @method static CarbonPeriod hours($hours = 1) Create instance specifying a number of hours for date interval.
- * @method static CarbonPeriod hour($hours = 1) Alias for hours().
- * @method static CarbonPeriod minutes($minutes = 1) Create instance specifying a number of minutes for date interval.
- * @method static CarbonPeriod minute($minutes = 1) Alias for minutes().
- * @method static CarbonPeriod seconds($seconds = 1) Create instance specifying a number of seconds for date interval.
- * @method static CarbonPeriod second($seconds = 1) Alias for seconds().
- * @method CarbonPeriod start($date, $inclusive = null) Change the period start date.
- * @method CarbonPeriod since($date, $inclusive = null) Alias for start().
- * @method CarbonPeriod sinceNow($inclusive = null) Change the period start date to now.
- * @method CarbonPeriod end($date = null, $inclusive = null) Change the period end date.
- * @method CarbonPeriod until($date = null, $inclusive = null) Alias for end().
- * @method CarbonPeriod untilNow($inclusive = null) Change the period end date to now.
- * @method CarbonPeriod dates($start, $end = null) Change the period start and end date.
- * @method CarbonPeriod recurrences($recurrences = null) Change the maximum number of recurrences.
- * @method CarbonPeriod times($recurrences = null) Alias for recurrences().
- * @method CarbonPeriod options($options = null) Change the period options.
- * @method CarbonPeriod toggle($options, $state = null) Toggle given options on or off.
- * @method CarbonPeriod filter($callback, $name = null) Add a filter to the stack.
- * @method CarbonPeriod push($callback, $name = null) Alias for filter().
- * @method CarbonPeriod prepend($callback, $name = null) Prepend a filter to the stack.
- * @method CarbonPeriod filters(array $filters = []) Set filters stack.
- * @method CarbonPeriod interval($interval) Change the period date interval.
- * @method CarbonPeriod invert() Invert the period date interval.
- * @method CarbonPeriod years($years = 1) Set the years portion of the date interval.
- * @method CarbonPeriod year($years = 1) Alias for years().
- * @method CarbonPeriod months($months = 1) Set the months portion of the date interval.
- * @method CarbonPeriod month($months = 1) Alias for months().
- * @method CarbonPeriod weeks($weeks = 1) Set the weeks portion of the date interval.
- * @method CarbonPeriod week($weeks = 1) Alias for weeks().
- * @method CarbonPeriod days($days = 1) Set the days portion of the date interval.
- * @method CarbonPeriod dayz($days = 1) Alias for days().
- * @method CarbonPeriod day($days = 1) Alias for days().
- * @method CarbonPeriod hours($hours = 1) Set the hours portion of the date interval.
- * @method CarbonPeriod hour($hours = 1) Alias for hours().
- * @method CarbonPeriod minutes($minutes = 1) Set the minutes portion of the date interval.
- * @method CarbonPeriod minute($minutes = 1) Alias for minutes().
- * @method CarbonPeriod seconds($seconds = 1) Set the seconds portion of the date interval.
- * @method CarbonPeriod second($seconds = 1) Alias for seconds().
- */
-class CarbonPeriod implements Iterator, Countable
-{
- use Options;
-
- /**
- * Built-in filters.
- *
- * @var string
- */
- const RECURRENCES_FILTER = 'Carbon\CarbonPeriod::filterRecurrences';
- const END_DATE_FILTER = 'Carbon\CarbonPeriod::filterEndDate';
-
- /**
- * Special value which can be returned by filters to end iteration. Also a filter.
- *
- * @var string
- */
- const END_ITERATION = 'Carbon\CarbonPeriod::endIteration';
-
- /**
- * Available options.
- *
- * @var int
- */
- const EXCLUDE_START_DATE = 1;
- const EXCLUDE_END_DATE = 2;
- const IMMUTABLE = 4;
-
- /**
- * Number of maximum attempts before giving up on finding next valid date.
- *
- * @var int
- */
- const NEXT_MAX_ATTEMPTS = 1000;
-
- /**
- * The registered macros.
- *
- * @var array
- */
- protected static $macros = [];
-
- /**
- * Date class of iteration items.
- *
- * @var string
- */
- protected $dateClass = Carbon::class;
-
- /**
- * Underlying date interval instance. Always present, one day by default.
- *
- * @var CarbonInterval
- */
- protected $dateInterval;
-
- /**
- * Whether current date interval was set by default.
- *
- * @var bool
- */
- protected $isDefaultInterval;
-
- /**
- * The filters stack.
- *
- * @var array
- */
- protected $filters = [];
-
- /**
- * Period start date. Applied on rewind. Always present, now by default.
- *
- * @var CarbonInterface
- */
- protected $startDate;
-
- /**
- * Period end date. For inverted interval should be before the start date. Applied via a filter.
- *
- * @var CarbonInterface|null
- */
- protected $endDate;
-
- /**
- * Limit for number of recurrences. Applied via a filter.
- *
- * @var int|null
- */
- protected $recurrences;
-
- /**
- * Iteration options.
- *
- * @var int
- */
- protected $options;
-
- /**
- * Index of current date. Always sequential, even if some dates are skipped by filters.
- * Equal to null only before the first iteration.
- *
- * @var int
- */
- protected $key;
-
- /**
- * Current date. May temporarily hold unaccepted value when looking for a next valid date.
- * Equal to null only before the first iteration.
- *
- * @var CarbonInterface
- */
- protected $current;
-
- /**
- * Timezone of current date. Taken from the start date.
- *
- * @var \DateTimeZone|null
- */
- protected $timezone;
-
- /**
- * The cached validation result for current date.
- *
- * @var bool|string|null
- */
- protected $validationResult;
-
- /**
- * Timezone handler for settings() method.
- *
- * @var mixed
- */
- protected $tzName;
-
- /**
- * Create a new instance.
- *
- * @return static
- */
- public static function create(...$params)
- {
- return static::createFromArray($params);
- }
-
- /**
- * Create a new instance from an array of parameters.
- *
- * @param array $params
- *
- * @return static
- */
- public static function createFromArray(array $params)
- {
- return new static(...$params);
- }
-
- /**
- * Create CarbonPeriod from ISO 8601 string.
- *
- * @param string $iso
- * @param int|null $options
- *
- * @return static
- */
- public static function createFromIso($iso, $options = null)
- {
- $params = static::parseIso8601($iso);
-
- $instance = static::createFromArray($params);
-
- if ($options !== null) {
- $instance->setOptions($options);
- }
-
- return $instance;
- }
-
- /**
- * Return whether given interval contains non zero value of any time unit.
- *
- * @param \DateInterval $interval
- *
- * @return bool
- */
- protected static function intervalHasTime(DateInterval $interval)
- {
- return $interval->h || $interval->i || $interval->s || $interval->f;
- }
-
- /**
- * Return whether given variable is an ISO 8601 specification.
- *
- * Note: Check is very basic, as actual validation will be done later when parsing.
- * We just want to ensure that variable is not any other type of a valid parameter.
- *
- * @param mixed $var
- *
- * @return bool
- */
- protected static function isIso8601($var)
- {
- if (!is_string($var)) {
- return false;
- }
-
- // Match slash but not within a timezone name.
- $part = '[a-z]+(?:[_-][a-z]+)*';
-
- preg_match("#\b$part/$part\b|(/)#i", $var, $match);
-
- return isset($match[1]);
- }
-
- /**
- * Parse given ISO 8601 string into an array of arguments.
- *
- * @param string $iso
- *
- * @return array
- */
- protected static function parseIso8601($iso)
- {
- $result = [];
-
- $interval = null;
- $start = null;
- $end = null;
-
- foreach (explode('/', $iso) as $key => $part) {
- if ($key === 0 && preg_match('/^R([0-9]*)$/', $part, $match)) {
- $parsed = strlen($match[1]) ? (int) $match[1] : null;
- } elseif ($interval === null && $parsed = CarbonInterval::make($part)) {
- $interval = $part;
- } elseif ($start === null && $parsed = Carbon::make($part)) {
- $start = $part;
- } elseif ($end === null && $parsed = Carbon::make(static::addMissingParts($start, $part))) {
- $end = $part;
- } else {
- throw new InvalidArgumentException("Invalid ISO 8601 specification: $iso.");
- }
-
- $result[] = $parsed;
- }
-
- return $result;
- }
-
- /**
- * Add missing parts of the target date from the soure date.
- *
- * @param string $source
- * @param string $target
- *
- * @return string
- */
- protected static function addMissingParts($source, $target)
- {
- $pattern = '/'.preg_replace('/[0-9]+/', '[0-9]+', preg_quote($target, '/')).'$/';
-
- $result = preg_replace($pattern, $target, $source, 1, $count);
-
- return $count ? $result : $target;
- }
-
- /**
- * Register a custom macro.
- *
- * @example
- * ```
- * CarbonPeriod::macro('middle', function () {
- * return $this->getStartDate()->average($this->getEndDate());
- * });
- * echo CarbonPeriod::since('2011-05-12')->until('2011-06-03')->middle();
- * ```
- *
- * @param string $name
- * @param object|callable $macro
- *
- * @return void
- */
- public static function macro($name, $macro)
- {
- static::$macros[$name] = $macro;
- }
-
- /**
- * Register macros from a mixin object.
- *
- * @example
- * ```
- * CarbonPeriod::mixin(new class {
- * public function addDays() {
- * return function ($count = 1) {
- * return $this->setStartDate(
- * $this->getStartDate()->addDays($count)
- * )->setEndDate(
- * $this->getEndDate()->addDays($count)
- * );
- * };
- * }
- * public function subDays() {
- * return function ($count = 1) {
- * return $this->setStartDate(
- * $this->getStartDate()->subDays($count)
- * )->setEndDate(
- * $this->getEndDate()->subDays($count)
- * );
- * };
- * }
- * });
- * echo CarbonPeriod::create('2000-01-01', '2000-02-01')->addDays(5)->subDays(3);
- * ```
- *
- * @param object $mixin
- *
- * @throws \ReflectionException
- *
- * @return void
- */
- public static function mixin($mixin)
- {
- $reflection = new ReflectionClass($mixin);
-
- $methods = $reflection->getMethods(
- ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
- );
-
- foreach ($methods as $method) {
- $method->setAccessible(true);
-
- static::macro($method->name, $method->invoke($mixin));
- }
- }
-
- /**
- * Check if macro is registered.
- *
- * @param string $name
- *
- * @return bool
- */
- public static function hasMacro($name)
- {
- return isset(static::$macros[$name]);
- }
-
- /**
- * Provide static proxy for instance aliases.
- *
- * @param string $method
- * @param array $parameters
- *
- * @return mixed
- */
- public static function __callStatic($method, $parameters)
- {
- return (new static)->$method(...$parameters);
- }
-
- /**
- * CarbonPeriod constructor.
- *
- * @throws InvalidArgumentException
- */
- public function __construct(...$arguments)
- {
- // Parse and assign arguments one by one. First argument may be an ISO 8601 spec,
- // which will be first parsed into parts and then processed the same way.
-
- if (count($arguments) && static::isIso8601($iso = $arguments[0])) {
- array_splice($arguments, 0, 1, static::parseIso8601($iso));
- }
-
- foreach ($arguments as $argument) {
- if ($this->dateInterval === null &&
- (
- is_string($argument) && preg_match('/^(\d.*|P[T0-9].*|(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+)$/i', $argument) ||
- $argument instanceof DateInterval
- ) &&
- $parsed = CarbonInterval::make($argument)
- ) {
- $this->setDateInterval($parsed);
- } elseif ($this->startDate === null && $parsed = Carbon::make($argument)) {
- $this->setStartDate($parsed);
- } elseif ($this->endDate === null && $parsed = Carbon::make($argument)) {
- $this->setEndDate($parsed);
- } elseif ($this->recurrences === null && $this->endDate === null && is_numeric($argument)) {
- $this->setRecurrences($argument);
- } elseif ($this->options === null && (is_int($argument) || $argument === null)) {
- $this->setOptions($argument);
- } else {
- throw new InvalidArgumentException('Invalid constructor parameters.');
- }
- }
-
- if ($this->startDate === null) {
- $this->setStartDate(Carbon::now());
- }
-
- if ($this->dateInterval === null) {
- $this->setDateInterval(CarbonInterval::day());
-
- $this->isDefaultInterval = true;
- }
-
- if ($this->options === null) {
- $this->setOptions(0);
- }
- }
-
- /**
- * Return whether given callable is a string pointing to one of Carbon's is* methods
- * and should be automatically converted to a filter callback.
- *
- * @param callable $callable
- *
- * @return bool
- */
- protected function isCarbonPredicateMethod($callable)
- {
- return is_string($callable) && substr($callable, 0, 2) === 'is' && (method_exists($this->dateClass, $callable) || call_user_func([$this->dateClass, 'hasMacro'], $callable));
- }
-
- /**
- * Set the iteration item class.
- *
- * @param string $dateClass
- *
- * @return $this
- */
- public function setDateClass(string $dateClass)
- {
- if (!is_a($dateClass, CarbonInterface::class, true)) {
- throw new InvalidArgumentException(sprintf(
- 'Given class does not implement %s: %s', CarbonInterface::class, $dateClass
- ));
- }
-
- $this->dateClass = $dateClass;
-
- if (is_a($dateClass, Carbon::class, true)) {
- $this->toggleOptions(static::IMMUTABLE, false);
- } elseif (is_a($dateClass, CarbonImmutable::class, true)) {
- $this->toggleOptions(static::IMMUTABLE, true);
- }
-
- return $this;
- }
-
- /**
- * Returns iteration item date class.
- *
- * @return string
- */
- public function getDateClass(): string
- {
- return $this->dateClass;
- }
-
- /**
- * Change the period date interval.
- *
- * @param DateInterval|string $interval
- *
- * @throws \InvalidArgumentException
- *
- * @return $this
- */
- public function setDateInterval($interval)
- {
- if (!$interval = CarbonInterval::make($interval)) {
- throw new InvalidArgumentException('Invalid interval.');
- }
-
- if ($interval->spec() === 'PT0S') {
- throw new InvalidArgumentException('Empty interval is not accepted.');
- }
-
- $this->dateInterval = $interval;
-
- $this->isDefaultInterval = false;
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Invert the period date interval.
- *
- * @return $this
- */
- public function invertDateInterval()
- {
- $interval = $this->dateInterval->invert();
-
- return $this->setDateInterval($interval);
- }
-
- /**
- * Set start and end date.
- *
- * @param DateTime|DateTimeInterface|string $start
- * @param DateTime|DateTimeInterface|string|null $end
- *
- * @return $this
- */
- public function setDates($start, $end)
- {
- $this->setStartDate($start);
- $this->setEndDate($end);
-
- return $this;
- }
-
- /**
- * Change the period options.
- *
- * @param int|null $options
- *
- * @throws \InvalidArgumentException
- *
- * @return $this
- */
- public function setOptions($options)
- {
- if (!is_int($options) && !is_null($options)) {
- throw new InvalidArgumentException('Invalid options.');
- }
-
- $this->options = $options ?: 0;
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Get the period options.
- *
- * @return int
- */
- public function getOptions()
- {
- return $this->options;
- }
-
- /**
- * Toggle given options on or off.
- *
- * @param int $options
- * @param bool|null $state
- *
- * @throws \InvalidArgumentException
- *
- * @return $this
- */
- public function toggleOptions($options, $state = null)
- {
- if ($state === null) {
- $state = ($this->options & $options) !== $options;
- }
-
- return $this->setOptions(
- $state ?
- $this->options | $options :
- $this->options & ~$options
- );
- }
-
- /**
- * Toggle EXCLUDE_START_DATE option.
- *
- * @param bool $state
- *
- * @return $this
- */
- public function excludeStartDate($state = true)
- {
- return $this->toggleOptions(static::EXCLUDE_START_DATE, $state);
- }
-
- /**
- * Toggle EXCLUDE_END_DATE option.
- *
- * @param bool $state
- *
- * @return $this
- */
- public function excludeEndDate($state = true)
- {
- return $this->toggleOptions(static::EXCLUDE_END_DATE, $state);
- }
-
- /**
- * Get the underlying date interval.
- *
- * @return CarbonInterval
- */
- public function getDateInterval()
- {
- return $this->dateInterval->copy();
- }
-
- /**
- * Get start date of the period.
- *
- * @return CarbonInterface
- */
- public function getStartDate()
- {
- return $this->startDate->copy();
- }
-
- /**
- * Get end date of the period.
- *
- * @return CarbonInterface|null
- */
- public function getEndDate()
- {
- return $this->endDate ? $this->endDate->copy() : null;
- }
-
- /**
- * Get number of recurrences.
- *
- * @return int|null
- */
- public function getRecurrences()
- {
- return $this->recurrences;
- }
-
- /**
- * Returns true if the start date should be excluded.
- *
- * @return bool
- */
- public function isStartExcluded()
- {
- return ($this->options & static::EXCLUDE_START_DATE) !== 0;
- }
-
- /**
- * Returns true if the end date should be excluded.
- *
- * @return bool
- */
- public function isEndExcluded()
- {
- return ($this->options & static::EXCLUDE_END_DATE) !== 0;
- }
-
- /**
- * Add a filter to the stack.
- *
- * @param callable $callback
- * @param string $name
- *
- * @return $this
- */
- public function addFilter($callback, $name = null)
- {
- $tuple = $this->createFilterTuple(func_get_args());
-
- $this->filters[] = $tuple;
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Prepend a filter to the stack.
- *
- * @param callable $callback
- * @param string $name
- *
- * @return $this
- */
- public function prependFilter($callback, $name = null)
- {
- $tuple = $this->createFilterTuple(func_get_args());
-
- array_unshift($this->filters, $tuple);
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Create a filter tuple from raw parameters.
- *
- * Will create an automatic filter callback for one of Carbon's is* methods.
- *
- * @param array $parameters
- *
- * @return array
- */
- protected function createFilterTuple(array $parameters)
- {
- $method = array_shift($parameters);
-
- if (!$this->isCarbonPredicateMethod($method)) {
- return [$method, array_shift($parameters)];
- }
-
- return [function ($date) use ($method, $parameters) {
- return call_user_func_array([$date, $method], $parameters);
- }, $method];
- }
-
- /**
- * Remove a filter by instance or name.
- *
- * @param callable|string $filter
- *
- * @return $this
- */
- public function removeFilter($filter)
- {
- $key = is_callable($filter) ? 0 : 1;
-
- $this->filters = array_values(array_filter(
- $this->filters,
- function ($tuple) use ($key, $filter) {
- return $tuple[$key] !== $filter;
- }
- ));
-
- $this->updateInternalState();
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Return whether given instance or name is in the filter stack.
- *
- * @param callable|string $filter
- *
- * @return bool
- */
- public function hasFilter($filter)
- {
- $key = is_callable($filter) ? 0 : 1;
-
- foreach ($this->filters as $tuple) {
- if ($tuple[$key] === $filter) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Get filters stack.
- *
- * @return array
- */
- public function getFilters()
- {
- return $this->filters;
- }
-
- /**
- * Set filters stack.
- *
- * @param array $filters
- *
- * @return $this
- */
- public function setFilters(array $filters)
- {
- $this->filters = $filters;
-
- $this->updateInternalState();
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Reset filters stack.
- *
- * @return $this
- */
- public function resetFilters()
- {
- $this->filters = [];
-
- if ($this->endDate !== null) {
- $this->filters[] = [static::END_DATE_FILTER, null];
- }
-
- if ($this->recurrences !== null) {
- $this->filters[] = [static::RECURRENCES_FILTER, null];
- }
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Update properties after removing built-in filters.
- *
- * @return void
- */
- protected function updateInternalState()
- {
- if (!$this->hasFilter(static::END_DATE_FILTER)) {
- $this->endDate = null;
- }
-
- if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
- $this->recurrences = null;
- }
- }
-
- /**
- * Add a recurrences filter (set maximum number of recurrences).
- *
- * @param int|null $recurrences
- *
- * @throws \InvalidArgumentException
- *
- * @return $this
- */
- public function setRecurrences($recurrences)
- {
- if (!is_numeric($recurrences) && !is_null($recurrences) || $recurrences < 0) {
- throw new InvalidArgumentException('Invalid number of recurrences.');
- }
-
- if ($recurrences === null) {
- return $this->removeFilter(static::RECURRENCES_FILTER);
- }
-
- $this->recurrences = (int) $recurrences;
-
- if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
- return $this->addFilter(static::RECURRENCES_FILTER);
- }
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * Recurrences filter callback (limits number of recurrences).
- *
- * @param \Carbon\Carbon $current
- * @param int $key
- *
- * @return bool|string
- */
- protected function filterRecurrences($current, $key)
- {
- if ($key < $this->recurrences) {
- return true;
- }
-
- return static::END_ITERATION;
- }
-
- /**
- * Change the period start date.
- *
- * @param DateTime|DateTimeInterface|string $date
- * @param bool|null $inclusive
- *
- * @throws \InvalidArgumentException
- *
- * @return $this
- */
- public function setStartDate($date, $inclusive = null)
- {
- if (!$date = call_user_func([$this->dateClass, 'make'], $date)) {
- throw new InvalidArgumentException('Invalid start date.');
- }
-
- $this->startDate = $date;
-
- if ($inclusive !== null) {
- $this->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive);
- }
-
- return $this;
- }
-
- /**
- * Change the period end date.
- *
- * @param DateTime|DateTimeInterface|string|null $date
- * @param bool|null $inclusive
- *
- * @throws \InvalidArgumentException
- *
- * @return $this
- */
- public function setEndDate($date, $inclusive = null)
- {
- if (!is_null($date) && !$date = call_user_func([$this->dateClass, 'make'], $date)) {
- throw new InvalidArgumentException('Invalid end date.');
- }
-
- if (!$date) {
- return $this->removeFilter(static::END_DATE_FILTER);
- }
-
- $this->endDate = $date;
-
- if ($inclusive !== null) {
- $this->toggleOptions(static::EXCLUDE_END_DATE, !$inclusive);
- }
-
- if (!$this->hasFilter(static::END_DATE_FILTER)) {
- return $this->addFilter(static::END_DATE_FILTER);
- }
-
- $this->handleChangedParameters();
-
- return $this;
- }
-
- /**
- * End date filter callback.
- *
- * @param \Carbon\Carbon $current
- *
- * @return bool|string
- */
- protected function filterEndDate($current)
- {
- if (!$this->isEndExcluded() && $current == $this->endDate) {
- return true;
- }
-
- if ($this->dateInterval->invert ? $current > $this->endDate : $current < $this->endDate) {
- return true;
- }
-
- return static::END_ITERATION;
- }
-
- /**
- * End iteration filter callback.
- *
- * @return string
- */
- protected function endIteration()
- {
- return static::END_ITERATION;
- }
-
- /**
- * Handle change of the parameters.
- */
- protected function handleChangedParameters()
- {
- if (($this->getOptions() & static::IMMUTABLE) && $this->dateClass === Carbon::class) {
- $this->setDateClass(CarbonImmutable::class);
- } elseif (!($this->getOptions() & static::IMMUTABLE) && $this->dateClass === CarbonImmutable::class) {
- $this->setDateClass(Carbon::class);
- }
-
- $this->validationResult = null;
- }
-
- /**
- * Validate current date and stop iteration when necessary.
- *
- * Returns true when current date is valid, false if it is not, or static::END_ITERATION
- * when iteration should be stopped.
- *
- * @return bool|string
- */
- protected function validateCurrentDate()
- {
- if ($this->current === null) {
- $this->rewind();
- }
-
- // Check after the first rewind to avoid repeating the initial validation.
- if ($this->validationResult !== null) {
- return $this->validationResult;
- }
-
- return $this->validationResult = $this->checkFilters();
- }
-
- /**
- * Check whether current value and key pass all the filters.
- *
- * @return bool|string
- */
- protected function checkFilters()
- {
- $current = $this->prepareForReturn($this->current);
-
- foreach ($this->filters as $tuple) {
- $result = call_user_func(
- $tuple[0],
- $current->copy(),
- $this->key,
- $this
- );
-
- if ($result === static::END_ITERATION) {
- return static::END_ITERATION;
- }
-
- if (!$result) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Prepare given date to be returned to the external logic.
- *
- * @param CarbonInterface $date
- *
- * @return Carbon
- */
- protected function prepareForReturn(CarbonInterface $date)
- {
- $date = call_user_func([$this->dateClass, 'make'], $date);
-
- if ($this->timezone) {
- $date = $date->setTimezone($this->timezone);
- }
-
- return $date;
- }
-
- /**
- * Check if the current position is valid.
- *
- * @return bool
- */
- public function valid()
- {
- return $this->validateCurrentDate() === true;
- }
-
- /**
- * Return the current key.
- *
- * @return int|null
- */
- public function key()
- {
- if ($this->valid()) {
- return $this->key;
- }
- }
-
- /**
- * Return the current date.
- *
- * @return Carbon|null
- */
- public function current()
- {
- if ($this->valid()) {
- return $this->prepareForReturn($this->current);
- }
- }
-
- /**
- * Move forward to the next date.
- *
- * @throws \RuntimeException
- *
- * @return void
- */
- public function next()
- {
- if ($this->current === null) {
- $this->rewind();
- }
-
- if ($this->validationResult !== static::END_ITERATION) {
- $this->key++;
-
- $this->incrementCurrentDateUntilValid();
- }
- }
-
- /**
- * Rewind to the start date.
- *
- * Iterating over a date in the UTC timezone avoids bug during backward DST change.
- *
- * @see https://bugs.php.net/bug.php?id=72255
- * @see https://bugs.php.net/bug.php?id=74274
- * @see https://wiki.php.net/rfc/datetime_and_daylight_saving_time
- *
- * @throws \RuntimeException
- *
- * @return void
- */
- public function rewind()
- {
- $this->key = 0;
- $this->current = call_user_func([$this->dateClass, 'make'], $this->startDate);
- $settings = $this->getSettings();
- $locale = $this->getLocalTranslator()->getLocale();
- if ($locale) {
- $settings['locale'] = $locale;
- }
- $this->current->settings($settings);
- $this->timezone = static::intervalHasTime($this->dateInterval) ? $this->current->getTimezone() : null;
-
- if ($this->timezone) {
- $this->current = $this->current->utc();
- }
-
- $this->validationResult = null;
-
- if ($this->isStartExcluded() || $this->validateCurrentDate() === false) {
- $this->incrementCurrentDateUntilValid();
- }
- }
-
- /**
- * Skip iterations and returns iteration state (false if ended, true if still valid).
- *
- * @param int $count steps number to skip (1 by default)
- *
- * @return bool
- */
- public function skip($count = 1)
- {
- for ($i = $count; $this->valid() && $i > 0; $i--) {
- $this->next();
- }
-
- return $this->valid();
- }
-
- /**
- * Keep incrementing the current date until a valid date is found or the iteration is ended.
- *
- * @throws \RuntimeException
- *
- * @return void
- */
- protected function incrementCurrentDateUntilValid()
- {
- $attempts = 0;
-
- do {
- $this->current = $this->current->add($this->dateInterval);
-
- $this->validationResult = null;
-
- if (++$attempts > static::NEXT_MAX_ATTEMPTS) {
- throw new RuntimeException('Could not find next valid date.');
- }
- } while ($this->validateCurrentDate() === false);
- }
-
- /**
- * Format the date period as ISO 8601.
- *
- * @return string
- */
- public function toIso8601String()
- {
- $parts = [];
-
- if ($this->recurrences !== null) {
- $parts[] = 'R'.$this->recurrences;
- }
-
- $parts[] = $this->startDate->toIso8601String();
-
- $parts[] = $this->dateInterval->spec();
-
- if ($this->endDate !== null) {
- $parts[] = $this->endDate->toIso8601String();
- }
-
- return implode('/', $parts);
- }
-
- /**
- * Convert the date period into a string.
- *
- * @return string
- */
- public function toString()
- {
- $translator = call_user_func([$this->dateClass, 'getTranslator']);
-
- $parts = [];
-
- $format = !$this->startDate->isStartOfDay() || $this->endDate && !$this->endDate->isStartOfDay()
- ? 'Y-m-d H:i:s'
- : 'Y-m-d';
-
- if ($this->recurrences !== null) {
- $parts[] = $this->translate('period_recurrences', [], $this->recurrences, $translator);
- }
-
- $parts[] = $this->translate('period_interval', [':interval' => $this->dateInterval->forHumans([
- 'join' => true,
- ])], null, $translator);
-
- $parts[] = $this->translate('period_start_date', [':date' => $this->startDate->rawFormat($format)], null, $translator);
-
- if ($this->endDate !== null) {
- $parts[] = $this->translate('period_end_date', [':date' => $this->endDate->rawFormat($format)], null, $translator);
- }
-
- $result = implode(' ', $parts);
-
- return mb_strtoupper(mb_substr($result, 0, 1)).mb_substr($result, 1);
- }
-
- /**
- * Format the date period as ISO 8601.
- *
- * @return string
- */
- public function spec()
- {
- return $this->toIso8601String();
- }
-
- /**
- * Convert the date period into an array without changing current iteration state.
- *
- * @return array
- */
- public function toArray()
- {
- $state = [
- $this->key,
- $this->current ? $this->current->copy() : null,
- $this->validationResult,
- ];
-
- $result = iterator_to_array($this);
-
- [
- $this->key,
- $this->current,
- $this->validationResult
- ] = $state;
-
- return $result;
- }
-
- /**
- * Count dates in the date period.
- *
- * @return int
- */
- public function count()
- {
- return count($this->toArray());
- }
-
- /**
- * Return the first date in the date period.
- *
- * @return Carbon|null
- */
- public function first()
- {
- if ($array = $this->toArray()) {
- return $array[0];
- }
- }
-
- /**
- * Return the last date in the date period.
- *
- * @return Carbon|null
- */
- public function last()
- {
- if ($array = $this->toArray()) {
- return $array[count($array) - 1];
- }
- }
-
- /**
- * Call given macro.
- *
- * @param string $name
- * @param array $parameters
- *
- * @return mixed
- */
- protected function callMacro($name, $parameters)
- {
- $macro = static::$macros[$name];
-
- if ($macro instanceof Closure) {
- return call_user_func_array($macro->bindTo($this, static::class), $parameters);
- }
-
- return call_user_func_array($macro, $parameters);
- }
-
- /**
- * Convert the date period into a string.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->toString();
- }
-
- /**
- * Add aliases for setters.
- *
- * CarbonPeriod::days(3)->hours(5)->invert()
- * ->sinceNow()->until('2010-01-10')
- * ->filter(...)
- * ->count()
- *
- * Note: We use magic method to let static and instance aliases with the same names.
- *
- * @param string $method
- * @param array $parameters
- *
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- if (static::hasMacro($method)) {
- return $this->callMacro($method, $parameters);
- }
-
- $first = count($parameters) >= 1 ? $parameters[0] : null;
- $second = count($parameters) >= 2 ? $parameters[1] : null;
-
- switch ($method) {
- case 'start':
- case 'since':
- return $this->setStartDate($first, $second);
-
- case 'sinceNow':
- return $this->setStartDate(new Carbon, $first);
-
- case 'end':
- case 'until':
- return $this->setEndDate($first, $second);
-
- case 'untilNow':
- return $this->setEndDate(new Carbon, $first);
-
- case 'dates':
- case 'between':
- return $this->setDates($first, $second);
-
- case 'recurrences':
- case 'times':
- return $this->setRecurrences($first);
-
- case 'options':
- return $this->setOptions($first);
-
- case 'toggle':
- return $this->toggleOptions($first, $second);
-
- case 'filter':
- case 'push':
- return $this->addFilter($first, $second);
-
- case 'prepend':
- return $this->prependFilter($first, $second);
-
- case 'filters':
- return $this->setFilters($first ?: []);
-
- case 'interval':
- case 'each':
- case 'every':
- case 'step':
- case 'stepBy':
- return $this->setDateInterval($first);
-
- case 'invert':
- return $this->invertDateInterval();
-
- case 'years':
- case 'year':
- case 'months':
- case 'month':
- case 'weeks':
- case 'week':
- case 'days':
- case 'dayz':
- case 'day':
- case 'hours':
- case 'hour':
- case 'minutes':
- case 'minute':
- case 'seconds':
- case 'second':
- return $this->setDateInterval(call_user_func(
- // Override default P1D when instantiating via fluent setters.
- [$this->isDefaultInterval ? new CarbonInterval('PT0S') : $this->dateInterval, $method],
- count($parameters) === 0 ? 1 : $first
- ));
- }
-
- if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
- throw new BadMethodCallException("Method $method does not exist.");
- }
-
- return $this;
- }
-
- public function shiftTimezone($timezone)
- {
- $this->tzName = $timezone;
- $this->timezone = $timezone;
-
- return $this;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use DateTimeInterface;
-use DateTimeZone;
-use InvalidArgumentException;
-
-class CarbonTimeZone extends DateTimeZone
-{
- public function __construct($timezone = null)
- {
- parent::__construct(static::getDateTimeZoneNameFromMixed($timezone));
- }
-
- protected static function getDateTimeZoneNameFromMixed($timezone)
- {
- if (is_null($timezone)) {
- $timezone = date_default_timezone_get();
- } elseif (is_numeric($timezone)) {
- if ($timezone <= -100 || $timezone >= 100) {
- throw new InvalidArgumentException('Absolute timezone offset cannot be greater than 100.');
- }
-
- $timezone = ($timezone >= 0 ? '+' : '').$timezone.':00';
- }
-
- return $timezone;
- }
-
- protected static function getDateTimeZoneFromName(&$name)
- {
- return @timezone_open($name = (string) static::getDateTimeZoneNameFromMixed($name));
- }
-
- /**
- * Create a CarbonTimeZone from mixed input.
- *
- * @param DateTimeZone|string|int|null $object original value to get CarbonTimeZone from it.
- * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages.
- *
- * @return false|static
- */
- public static function instance($object = null, $objectDump = null)
- {
- $tz = $object;
-
- if ($tz instanceof static) {
- return $tz;
- }
-
- if ($tz === null) {
- return new static();
- }
-
- if (!$tz instanceof DateTimeZone) {
- $tz = static::getDateTimeZoneFromName($object);
- }
-
- if ($tz === false) {
- if (Carbon::isStrictModeEnabled()) {
- throw new InvalidArgumentException('Unknown or bad timezone ('.($objectDump ?: $object).')');
- }
-
- return false;
- }
-
- return new static($tz->getName());
- }
-
- /**
- * Returns abbreviated name of the current timezone according to DST setting.
- *
- * @param bool $dst
- *
- * @return string
- */
- public function getAbbreviatedName($dst = false)
- {
- $name = $this->getName();
-
- foreach ($this->listAbbreviations() as $abbreviation => $zones) {
- foreach ($zones as $zone) {
- if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) {
- return $abbreviation;
- }
- }
- }
-
- return 'unknown';
- }
-
- /**
- * @alias getAbbreviatedName
- *
- * Returns abbreviated name of the current timezone according to DST setting.
- *
- * @param bool $dst
- *
- * @return string
- */
- public function getAbbr($dst = false)
- {
- return $this->getAbbreviatedName($dst);
- }
-
- /**
- * Get the offset as string "sHH:MM" (such as "+00:00" or "-12:30").
- *
- * @param DateTimeInterface|null $date
- *
- * @return string
- */
- public function toOffsetName(DateTimeInterface $date = null)
- {
- $minutes = floor($this->getOffset($date ?: Carbon::now($this)) / 60);
-
- $hours = floor($minutes / 60);
-
- $minutes = str_pad((string) (abs($minutes) % 60), 2, '0', STR_PAD_LEFT);
-
- return ($hours < 0 ? '-' : '+').str_pad((string) abs($hours), 2, '0', STR_PAD_LEFT).":$minutes";
- }
-
- /**
- * Returns a new CarbonTimeZone object using the offset string instead of region string.
- *
- * @param DateTimeInterface|null $date
- *
- * @return CarbonTimeZone
- */
- public function toOffsetTimeZone(DateTimeInterface $date = null)
- {
- return new static($this->toOffsetName($date));
- }
-
- /**
- * Returns the first region string (such as "America/Toronto") that matches the current timezone.
- *
- * @see timezone_name_from_abbr native PHP function.
- *
- * @param DateTimeInterface|null $date
- * @param int $isDst
- *
- * @return string
- */
- public function toRegionName(DateTimeInterface $date = null, $isDst = 1)
- {
- $name = $this->getName();
- $firstChar = substr($name, 0, 1);
-
- if ($firstChar !== '+' && $firstChar !== '-') {
- return $name;
- }
-
- return @timezone_name_from_abbr('', @$this->getOffset($date ?: Carbon::now($this)) ?: 0, $isDst);
- }
-
- /**
- * Returns a new CarbonTimeZone object using the region string instead of offset string.
- *
- * @param DateTimeInterface|null $date
- *
- * @return CarbonTimeZone|false
- */
- public function toRegionTimeZone(DateTimeInterface $date = null)
- {
- $tz = $this->toRegionName($date);
-
- if ($tz === false) {
- if (Carbon::isStrictModeEnabled()) {
- throw new InvalidArgumentException('Unknown timezone for offset '.$this->getOffset($date ?: Carbon::now($this)).' seconds.');
- }
-
- return false;
- }
-
- return new static($tz);
- }
-
- /**
- * Cast to string (get timezone name).
- *
- * @return string
- */
- public function __toString()
- {
- return $this->getName();
- }
-
- /**
- * Create a CarbonTimeZone from mixed input.
- *
- * @param DateTimeZone|string|int|null $object
- *
- * @return false|static
- */
- public static function create($object = null)
- {
- return static::instance($object);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Exceptions;
-
-use Exception;
-use InvalidArgumentException;
-
-class InvalidDateException extends InvalidArgumentException
-{
- /**
- * The invalid field.
- *
- * @var string
- */
- private $field;
-
- /**
- * The invalid value.
- *
- * @var mixed
- */
- private $value;
-
- /**
- * Constructor.
- *
- * @param string $field
- * @param mixed $value
- * @param int $code
- * @param \Exception|null $previous
- */
- public function __construct($field, $value, $code = 0, Exception $previous = null)
- {
- $this->field = $field;
- $this->value = $value;
- parent::__construct($field.' : '.$value.' is not a valid value.', $code, $previous);
- }
-
- /**
- * Get the invalid field.
- *
- * @return string
- */
- public function getField()
- {
- return $this->field;
- }
-
- /**
- * Get the invalid value.
- *
- * @return mixed
- */
- public function getValue()
- {
- return $this->value;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-/**
- * A factory to generate Carbon instances with common settings.
- *
- * <autodoc generated by `composer phpdoc`>
- *
- * @method Carbon create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) Create a new Carbon instance from a specific date and time.
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- * @method Carbon createFromDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to now.
- * @method Carbon|false createFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
- * @method Carbon|false createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
- * @method Carbon|false createFromLocaleFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific format and a string in a given language.
- * @method Carbon|false createFromLocaleIsoFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific ISO format and a string in a given language.
- * @method Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) Create a Carbon instance from just a time. The date portion is set to today.
- * @method Carbon createFromTimeString($time, $tz = null) Create a Carbon instance from a time string. The date portion is set to today.
- * @method Carbon createFromTimestamp($timestamp, $tz = null) Create a Carbon instance from a timestamp.
- * @method Carbon createFromTimestampMs($timestamp, $tz = null) Create a Carbon instance from a timestamp in milliseconds.
- * @method Carbon createFromTimestampUTC($timestamp) Create a Carbon instance from an UTC timestamp.
- * @method Carbon createMidnightDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to midnight.
- * @method Carbon|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) Create a new safe Carbon instance from a specific date and time.
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- * If one of the set values is not valid, an \InvalidArgumentException
- * will be thrown.
- * @method Carbon disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method Carbon enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method mixed executeWithLocale($locale, $func) Set the current locale to the given, execute the passed function, reset the locale to previous one,
- * then return the result of the closure (or null if the closure was void).
- * @method Carbon fromSerialized($value) Create an instance from a serialized string.
- * @method void genericMacro($macro, $priority = 0) Register a custom macro.
- * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales.
- * (It will ignore custom translator dynamic loading.)
- * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native
- * name, region and variant of the locale.
- * @method array getDays() Get the days of the week
- * @method string|null getFallbackLocale() Get the fallback locale.
- * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat().
- * @method int getHumanDiffOptions() Return default humanDiff() options (merged flags as integer).
- * @method array getIsoUnits() Returns list of locale units for ISO formatting.
- * @method Carbon getLastErrors() {@inheritdoc}
- * @method string getLocale() Get the current translator locale.
- * @method int getMidDayAt() get midday/noon hour
- * @method Carbon getTestNow() Get the Carbon instance (real or mock) to be returned when a "now"
- * instance is created.
- * @method string getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null) Returns raw translation message for a given key.
- * @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use.
- * @method int getWeekEndsAt() Get the last day of week
- * @method int getWeekStartsAt() Get the first day of week
- * @method array getWeekendDays() Get weekend days
- * @method bool hasFormat($date, $format) Checks if the (date)time string is in a given format.
- * @method bool hasMacro($name) Checks if macro is registered.
- * @method bool hasRelativeKeywords($time) Determine if a time string will produce a relative date.
- * @method bool hasTestNow() Determine if there is a valid test instance set. A valid test instance
- * is anything that is not null.
- * @method Carbon instance($date) Create a Carbon instance from a DateTime one.
- * @method bool isImmutable() Returns true if the current class/instance is immutable.
- * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter.
- * @method Carbon isMutable()
- * @method bool isStrictModeEnabled() Returns true if the strict mode is globally in use, false else.
- * (It can be overridden in specific instances.)
- * @method bool localeHasDiffOneDayWords($locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
- * Support is considered enabled if the 3 words are translated in the given locale.
- * @method bool localeHasDiffSyntax($locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- * @method bool localeHasDiffTwoDayWords($locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
- * Support is considered enabled if the 2 words are translated in the given locale.
- * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- * @method bool localeHasShortUnits($locale) Returns true if the given locale is internally supported and has short-units support.
- * Support is considered enabled if either year, day or hour has a short variant translated.
- * @method void macro($name, $macro) Register a custom macro.
- * @method Carbon|null make($var) Make a Carbon instance from given variable if possible.
- * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
- * and recurrences). Throw an exception for invalid format, but otherwise return null.
- * @method Carbon maxValue() Create a Carbon instance for the greatest supported date.
- * @method Carbon minValue() Create a Carbon instance for the lowest supported date.
- * @method void mixin($mixin) Mix another object into the class.
- * @method Carbon now($tz = null) Get a Carbon instance for the current date and time.
- * @method Carbon parse($time = null, $tz = null) Create a carbon instance from a string.
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- * @method Carbon parseFromLocale($time, $locale, $tz = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
- * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English).
- * @method Carbon|false rawCreateFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
- * @method Carbon rawParse($time = null, $tz = null) Create a carbon instance from a string.
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- * @method Carbon resetMacros() Remove all macros and generic macros.
- * @method void resetMonthsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method void resetToStringFormat() Reset the format used to the default when type juggling a Carbon instance to a string
- * @method void resetYearsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method void serializeUsing($callback) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather transform Carbon object before the serialization.
- * JSON serialize all Carbon instances using the given callback.
- * @method Carbon setFallbackLocale($locale) Set the fallback locale.
- * @method Carbon setHumanDiffOptions($humanDiffOptions) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method bool setLocale($locale) Set the current translator locale and indicate if the source locale file exists.
- * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
- * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
- * hour, test it explicitly:
- * $date->format('G') == 13
- * or to set explicitly to a given hour:
- * $date->setTime(13, 0, 0, 0)
- * Set midday/noon hour
- * @method Carbon setTestNow($testNow = null) Set a Carbon instance (real or mock) to be returned when a "now"
- * instance is created. The provided instance will be returned
- * specifically under the following conditions:
- * - A call to the static now() method, ex. Carbon::now()
- * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
- * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
- * - When a string containing the desired time is passed to Carbon::parse().
- * Note the timezone parameter was left out of the examples above and
- * has no affect as the mock value will be returned regardless of its value.
- * To clear the test instance call this method using the default
- * parameter of null.
- * /!\ Use this method for unit tests only.
- * @method void setToStringFormat($format) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
- * use other method or custom format passed to format() method if you need to dump an other string
- * format.
- * Set the default format used when type juggling a Carbon instance to a string
- * @method void setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator) Set the default translator instance to use.
- * @method Carbon setUtf8($utf8) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use UTF-8 language packages on every machine.
- * Set if UTF8 will be used for localized date/time.
- * @method void setWeekEndsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
- * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
- * start of week according to current locale selected and implicitly the end of week.
- * Set the last day of week
- * @method void setWeekStartsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
- * 'first_day_of_week' locale setting to change the start of week according to current locale
- * selected and implicitly the end of week.
- * Set the first day of week
- * @method void setWeekendDays($days) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider week-end is always saturday and sunday, and if you have some custom
- * week-end days to handle, give to those days an other name and create a macro for them:
- * ```
- * Carbon::macro('isDayOff', function ($date) {
- * return $date->isSunday() || $date->isMonday();
- * });
- * Carbon::macro('isNotDayOff', function ($date) {
- * return !$date->isDayOff();
- * });
- * if ($someDate->isDayOff()) ...
- * if ($someDate->isNotDayOff()) ...
- * // Add 5 not-off days
- * $count = 5;
- * while ($someDate->isDayOff() || ($count-- > 0)) {
- * $someDate->addDay();
- * }
- * ```
- * Set weekend days
- * @method bool shouldOverflowMonths() Get the month overflow global behavior (can be overridden in specific instances).
- * @method bool shouldOverflowYears() Get the month overflow global behavior (can be overridden in specific instances).
- * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English).
- * @method Carbon today($tz = null) Create a Carbon instance for today.
- * @method Carbon tomorrow($tz = null) Create a Carbon instance for tomorrow.
- * @method string translateTimeString($timeString, $from = null, $to = null, $mode = 15) Translate a time string from a locale to an other.
- * @method string translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available.
- * @method void useMonthsOverflow($monthsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method Carbon useStrictMode($strictModeEnabled = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method void useYearsOverflow($yearsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method Carbon yesterday($tz = null) Create a Carbon instance for yesterday.
- *
- * </autodoc>
- */
-class Factory
-{
- protected $className = Carbon::class;
-
- protected $settings = [];
-
- public function __construct(array $settings = [], string $className = null)
- {
- if ($className) {
- $this->className = $className;
- }
- $this->settings = $settings;
- }
-
- public function getClassName()
- {
- return $this->className;
- }
-
- public function setClassName(string $className)
- {
- $this->className = $className;
-
- return $this;
- }
-
- public function className(string $className = null)
- {
- return $className === null ? $this->getClassName() : $this->setClassName($className);
- }
-
- public function getSettings()
- {
- return $this->settings;
- }
-
- public function setSettings(array $settings)
- {
- $this->settings = $settings;
-
- return $this;
- }
-
- public function settings(array $settings = null)
- {
- return $settings === null ? $this->getSettings() : $this->setSettings($settings);
- }
-
- public function mergeSettings(array $settings)
- {
- $this->settings = array_merge($this->settings, $settings);
-
- return $this;
- }
-
- public function __call($name, $arguments)
- {
- $result = $this->className::$name(...$arguments);
-
- return $result instanceof CarbonInterface ? $result->settings($this->settings) : $result;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-/**
- * A factory to generate CarbonImmutable instances with common settings.
- *
- * <autodoc generated by `composer phpdoc`>
- *
- * @method CarbonImmutable create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) Create a new Carbon instance from a specific date and time.
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- * @method CarbonImmutable createFromDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to now.
- * @method CarbonImmutable|false createFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
- * @method CarbonImmutable|false createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
- * @method CarbonImmutable|false createFromLocaleFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific format and a string in a given language.
- * @method CarbonImmutable|false createFromLocaleIsoFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific ISO format and a string in a given language.
- * @method CarbonImmutable createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) Create a Carbon instance from just a time. The date portion is set to today.
- * @method CarbonImmutable createFromTimeString($time, $tz = null) Create a Carbon instance from a time string. The date portion is set to today.
- * @method CarbonImmutable createFromTimestamp($timestamp, $tz = null) Create a Carbon instance from a timestamp.
- * @method CarbonImmutable createFromTimestampMs($timestamp, $tz = null) Create a Carbon instance from a timestamp in milliseconds.
- * @method CarbonImmutable createFromTimestampUTC($timestamp) Create a Carbon instance from an UTC timestamp.
- * @method CarbonImmutable createMidnightDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to midnight.
- * @method CarbonImmutable|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) Create a new safe Carbon instance from a specific date and time.
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- * If one of the set values is not valid, an \InvalidArgumentException
- * will be thrown.
- * @method CarbonImmutable disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method CarbonImmutable enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method mixed executeWithLocale($locale, $func) Set the current locale to the given, execute the passed function, reset the locale to previous one,
- * then return the result of the closure (or null if the closure was void).
- * @method CarbonImmutable fromSerialized($value) Create an instance from a serialized string.
- * @method void genericMacro($macro, $priority = 0) Register a custom macro.
- * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales.
- * (It will ignore custom translator dynamic loading.)
- * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native
- * name, region and variant of the locale.
- * @method array getDays() Get the days of the week
- * @method string|null getFallbackLocale() Get the fallback locale.
- * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat().
- * @method int getHumanDiffOptions() Return default humanDiff() options (merged flags as integer).
- * @method array getIsoUnits() Returns list of locale units for ISO formatting.
- * @method CarbonImmutable getLastErrors() {@inheritdoc}
- * @method string getLocale() Get the current translator locale.
- * @method int getMidDayAt() get midday/noon hour
- * @method CarbonImmutable getTestNow() Get the Carbon instance (real or mock) to be returned when a "now"
- * instance is created.
- * @method string getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null) Returns raw translation message for a given key.
- * @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use.
- * @method int getWeekEndsAt() Get the last day of week
- * @method int getWeekStartsAt() Get the first day of week
- * @method array getWeekendDays() Get weekend days
- * @method bool hasFormat($date, $format) Checks if the (date)time string is in a given format.
- * @method bool hasMacro($name) Checks if macro is registered.
- * @method bool hasRelativeKeywords($time) Determine if a time string will produce a relative date.
- * @method bool hasTestNow() Determine if there is a valid test instance set. A valid test instance
- * is anything that is not null.
- * @method CarbonImmutable instance($date) Create a Carbon instance from a DateTime one.
- * @method bool isImmutable() Returns true if the current class/instance is immutable.
- * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter.
- * @method CarbonImmutable isMutable()
- * @method bool isStrictModeEnabled() Returns true if the strict mode is globally in use, false else.
- * (It can be overridden in specific instances.)
- * @method bool localeHasDiffOneDayWords($locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
- * Support is considered enabled if the 3 words are translated in the given locale.
- * @method bool localeHasDiffSyntax($locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- * @method bool localeHasDiffTwoDayWords($locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
- * Support is considered enabled if the 2 words are translated in the given locale.
- * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- * @method bool localeHasShortUnits($locale) Returns true if the given locale is internally supported and has short-units support.
- * Support is considered enabled if either year, day or hour has a short variant translated.
- * @method void macro($name, $macro) Register a custom macro.
- * @method CarbonImmutable|null make($var) Make a Carbon instance from given variable if possible.
- * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
- * and recurrences). Throw an exception for invalid format, but otherwise return null.
- * @method CarbonImmutable maxValue() Create a Carbon instance for the greatest supported date.
- * @method CarbonImmutable minValue() Create a Carbon instance for the lowest supported date.
- * @method void mixin($mixin) Mix another object into the class.
- * @method CarbonImmutable now($tz = null) Get a Carbon instance for the current date and time.
- * @method CarbonImmutable parse($time = null, $tz = null) Create a carbon instance from a string.
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- * @method CarbonImmutable parseFromLocale($time, $locale, $tz = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
- * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English).
- * @method CarbonImmutable|false rawCreateFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
- * @method CarbonImmutable rawParse($time = null, $tz = null) Create a carbon instance from a string.
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- * @method CarbonImmutable resetMacros() Remove all macros and generic macros.
- * @method void resetMonthsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method void resetToStringFormat() Reset the format used to the default when type juggling a Carbon instance to a string
- * @method void resetYearsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method void serializeUsing($callback) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather transform Carbon object before the serialization.
- * JSON serialize all Carbon instances using the given callback.
- * @method CarbonImmutable setFallbackLocale($locale) Set the fallback locale.
- * @method CarbonImmutable setHumanDiffOptions($humanDiffOptions) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method bool setLocale($locale) Set the current translator locale and indicate if the source locale file exists.
- * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
- * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
- * hour, test it explicitly:
- * $date->format('G') == 13
- * or to set explicitly to a given hour:
- * $date->setTime(13, 0, 0, 0)
- * Set midday/noon hour
- * @method CarbonImmutable setTestNow($testNow = null) Set a Carbon instance (real or mock) to be returned when a "now"
- * instance is created. The provided instance will be returned
- * specifically under the following conditions:
- * - A call to the static now() method, ex. Carbon::now()
- * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
- * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
- * - When a string containing the desired time is passed to Carbon::parse().
- * Note the timezone parameter was left out of the examples above and
- * has no affect as the mock value will be returned regardless of its value.
- * To clear the test instance call this method using the default
- * parameter of null.
- * /!\ Use this method for unit tests only.
- * @method void setToStringFormat($format) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
- * use other method or custom format passed to format() method if you need to dump an other string
- * format.
- * Set the default format used when type juggling a Carbon instance to a string
- * @method void setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator) Set the default translator instance to use.
- * @method CarbonImmutable setUtf8($utf8) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use UTF-8 language packages on every machine.
- * Set if UTF8 will be used for localized date/time.
- * @method void setWeekEndsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
- * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
- * start of week according to current locale selected and implicitly the end of week.
- * Set the last day of week
- * @method void setWeekStartsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
- * 'first_day_of_week' locale setting to change the start of week according to current locale
- * selected and implicitly the end of week.
- * Set the first day of week
- * @method void setWeekendDays($days) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider week-end is always saturday and sunday, and if you have some custom
- * week-end days to handle, give to those days an other name and create a macro for them:
- * ```
- * Carbon::macro('isDayOff', function ($date) {
- * return $date->isSunday() || $date->isMonday();
- * });
- * Carbon::macro('isNotDayOff', function ($date) {
- * return !$date->isDayOff();
- * });
- * if ($someDate->isDayOff()) ...
- * if ($someDate->isNotDayOff()) ...
- * // Add 5 not-off days
- * $count = 5;
- * while ($someDate->isDayOff() || ($count-- > 0)) {
- * $someDate->addDay();
- * }
- * ```
- * Set weekend days
- * @method bool shouldOverflowMonths() Get the month overflow global behavior (can be overridden in specific instances).
- * @method bool shouldOverflowYears() Get the month overflow global behavior (can be overridden in specific instances).
- * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English).
- * @method CarbonImmutable today($tz = null) Create a Carbon instance for today.
- * @method CarbonImmutable tomorrow($tz = null) Create a Carbon instance for tomorrow.
- * @method string translateTimeString($timeString, $from = null, $to = null, $mode = 15) Translate a time string from a locale to an other.
- * @method string translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available.
- * @method void useMonthsOverflow($monthsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method CarbonImmutable useStrictMode($strictModeEnabled = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @method void useYearsOverflow($yearsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method CarbonImmutable yesterday($tz = null) Create a Carbon instance for yesterday.
- *
- * </autodoc>
- */
-class FactoryImmutable extends Factory
-{
- protected $className = CarbonImmutable::class;
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/aa_DJ.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
- 'months_short' => ['qun', 'nah', 'cig', 'agd', 'cax', 'qas', 'qad', 'leq', 'way', 'dit', 'xim', 'kax'],
- 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
- 'weekdays_short' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'],
- 'weekdays_min' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['saaku', 'carra'],
-
- 'year' => ':count gaqambo', // less reliable
- 'y' => ':count gaqambo', // less reliable
- 'a_year' => ':count gaqambo', // less reliable
-
- 'month' => ':count àlsa',
- 'm' => ':count àlsa',
- 'a_month' => ':count àlsa',
-
- 'day' => ':count saaku', // less reliable
- 'd' => ':count saaku', // less reliable
- 'a_day' => ':count saaku', // less reliable
-
- 'hour' => ':count ayti', // less reliable
- 'h' => ':count ayti', // less reliable
- 'a_hour' => ':count ayti', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
- 'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
- 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
- 'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
- 'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['saaku', 'carra'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
- 'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
- 'weekdays' => ['Naba Sambat', 'Sani', 'Salus', 'Rabuq', 'Camus', 'Jumqata', 'Qunxa Sambat'],
- 'weekdays_short' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
- 'weekdays_min' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['saaku', 'carra'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
- 'months_short' => ['Qun', 'Kud', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
- 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
- 'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
- 'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['saaku', 'carra'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - JD Isaacks
- * - Pierre du Plessis
- */
-return [
- 'year' => ':count jaar|:count jare',
- 'a_year' => '\'n jaar|:count jare',
- 'y' => ':count j.',
- 'month' => ':count maand|:count maande',
- 'a_month' => '\'n maand|:count maande',
- 'm' => ':count maa.',
- 'week' => ':count week|:count weke',
- 'a_week' => '\'n week|:count weke',
- 'w' => ':count w.',
- 'day' => ':count dag|:count dae',
- 'a_day' => '\'n dag|:count dae',
- 'd' => ':count d.',
- 'hour' => ':count uur|:count ure',
- 'a_hour' => '\'n uur|:count ure',
- 'h' => ':count u.',
- 'minute' => ':count minuut|:count minute',
- 'a_minute' => '\'n minuut|:count minute',
- 'min' => ':count min.',
- 'second' => ':count sekond|:count sekondes',
- 'a_second' => '\'n paar sekondes|:count sekondes',
- 's' => ':count s.',
- 'ago' => ':time gelede',
- 'from_now' => 'oor :time',
- 'after' => ':time na',
- 'before' => ':time voor',
- 'diff_yesterday' => 'Gister',
- 'diff_tomorrow' => 'Môre',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Vandag om] LT',
- 'nextDay' => '[Môre om] LT',
- 'nextWeek' => 'dddd [om] LT',
- 'lastDay' => '[Gister om] LT',
- 'lastWeek' => '[Laas] dddd [om] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
- },
- 'meridiem' => ['VM', 'NM'],
- 'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
- 'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
- 'weekdays_short' => ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
- 'weekdays_min' => ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' en '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/af.php', [
- 'meridiem' => ['v', 'n'],
- 'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
- 'weekdays_short' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'],
- 'weekdays_min' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'],
- 'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
- 'months_short' => ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Des.'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'DD MMM YYYY',
- 'LLL' => 'DD MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, DD MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/af.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['a.g', 'a.k'],
- 'weekdays' => ['tsuʔntsɨ', 'tsuʔukpà', 'tsuʔughɔe', 'tsuʔutɔ̀mlò', 'tsuʔumè', 'tsuʔughɨ̂m', 'tsuʔndzɨkɔʔɔ'],
- 'weekdays_short' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
- 'weekdays_min' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
- 'months' => ['ndzɔ̀ŋɔ̀nùm', 'ndzɔ̀ŋɔ̀kƗ̀zùʔ', 'ndzɔ̀ŋɔ̀tƗ̀dʉ̀ghà', 'ndzɔ̀ŋɔ̀tǎafʉ̄ghā', 'ndzɔ̀ŋèsèe', 'ndzɔ̀ŋɔ̀nzùghò', 'ndzɔ̀ŋɔ̀dùmlo', 'ndzɔ̀ŋɔ̀kwîfɔ̀e', 'ndzɔ̀ŋɔ̀tƗ̀fʉ̀ghàdzughù', 'ndzɔ̀ŋɔ̀ghǔuwelɔ̀m', 'ndzɔ̀ŋɔ̀chwaʔàkaa wo', 'ndzɔ̀ŋèfwòo'],
- 'months_short' => ['nùm', 'kɨz', 'tɨd', 'taa', 'see', 'nzu', 'dum', 'fɔe', 'dzu', 'lɔm', 'kaa', 'fwo'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/agr_PE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - somosazucar.org libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Petsatin', 'Kupitin', 'Uyaitin', 'Tayutin', 'Kegketin', 'Tegmatin', 'Kuntutin', 'Yagkujutin', 'Daiktatin', 'Ipamtatin', 'Shinutin', 'Sakamtin'],
- 'months_short' => ['Pet', 'Kup', 'Uya', 'Tay', 'Keg', 'Teg', 'Kun', 'Yag', 'Dait', 'Ipam', 'Shin', 'Sak'],
- 'weekdays' => ['Tuntuamtin', 'Achutin', 'Kugkuktin', 'Saketin', 'Shimpitin', 'Imaptin', 'Bataetin'],
- 'weekdays_short' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'],
- 'weekdays_min' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 7,
- 'meridiem' => ['VM', 'NM'],
-
- 'year' => ':count yaya', // less reliable
- 'y' => ':count yaya', // less reliable
- 'a_year' => ':count yaya', // less reliable
-
- 'month' => ':count nantu', // less reliable
- 'm' => ':count nantu', // less reliable
- 'a_month' => ':count nantu', // less reliable
-
- 'day' => ':count nayaim', // less reliable
- 'd' => ':count nayaim', // less reliable
- 'a_day' => ':count nayaim', // less reliable
-
- 'hour' => ':count kuwiš', // less reliable
- 'h' => ':count kuwiš', // less reliable
- 'a_hour' => ':count kuwiš', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ak_GH.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY/MM/DD',
- ],
- 'months' => ['Sanda-Ɔpɛpɔn', 'Kwakwar-Ɔgyefuo', 'Ebɔw-Ɔbenem', 'Ebɔbira-Oforisuo', 'Esusow Aketseaba-Kɔtɔnimba', 'Obirade-Ayɛwohomumu', 'Ayɛwoho-Kitawonsa', 'Difuu-Ɔsandaa', 'Fankwa-Ɛbɔ', 'Ɔbɛsɛ-Ahinime', 'Ɔberɛfɛw-Obubuo', 'Mumu-Ɔpɛnimba'],
- 'months_short' => ['S-Ɔ', 'K-Ɔ', 'E-Ɔ', 'E-O', 'E-K', 'O-A', 'A-K', 'D-Ɔ', 'F-Ɛ', 'Ɔ-A', 'Ɔ-O', 'M-Ɔ'],
- 'weekdays' => ['Kwesida', 'Dwowda', 'Benada', 'Wukuda', 'Yawda', 'Fida', 'Memeneda'],
- 'weekdays_short' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
- 'weekdays_min' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['AN', 'EW'],
-
- 'year' => ':count afe',
- 'y' => ':count afe',
- 'a_year' => ':count afe',
-
- 'month' => ':count bosume',
- 'm' => ':count bosume',
- 'a_month' => ':count bosume',
-
- 'day' => ':count ɛda',
- 'd' => ':count ɛda',
- 'a_day' => ':count ɛda',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/am_ET.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕሪል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክቶበር', 'ኖቬምበር', 'ዲሴምበር'],
- 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
- 'weekdays' => ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
- 'weekdays_short' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
- 'weekdays_min' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ጡዋት', 'ከሰዓት'],
-
- 'year' => ':count አመት',
- 'y' => ':count አመት',
- 'a_year' => ':count አመት',
-
- 'month' => ':count ወር',
- 'm' => ':count ወር',
- 'a_month' => ':count ወር',
-
- 'week' => ':count ሳምንት',
- 'w' => ':count ሳምንት',
- 'a_week' => ':count ሳምንት',
-
- 'day' => ':count ቀን',
- 'd' => ':count ቀን',
- 'a_day' => ':count ቀን',
-
- 'hour' => ':count ሰዓት',
- 'h' => ':count ሰዓት',
- 'a_hour' => ':count ሰዓት',
-
- 'minute' => ':count ደቂቃ',
- 'min' => ':count ደቂቃ',
- 'a_minute' => ':count ደቂቃ',
-
- 'second' => ':count ሴኮንድ',
- 's' => ':count ሴኮንድ',
- 'a_second' => ':count ሴኮንድ',
-
- 'ago' => 'ከ:time በፊት',
- 'from_now' => 'በ:time ውስጥ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/an_ES.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Softaragones Jordi Mallach Pérez, Juan Pablo Martínez bug-glibc-locales@gnu.org, softaragones@softaragones.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['chinero', 'febrero', 'marzo', 'abril', 'mayo', 'chunyo', 'chuliol', 'agosto', 'setiembre', 'octubre', 'noviembre', 'aviento'],
- 'months_short' => ['chi', 'feb', 'mar', 'abr', 'may', 'chn', 'chl', 'ago', 'set', 'oct', 'nov', 'avi'],
- 'weekdays' => ['domingo', 'luns', 'martes', 'mierques', 'chueves', 'viernes', 'sabado'],
- 'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'],
- 'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count año',
- 'y' => ':count año',
- 'a_year' => ':count año',
-
- 'month' => ':count mes',
- 'm' => ':count mes',
- 'a_month' => ':count mes',
-
- 'week' => ':count semana',
- 'w' => ':count semana',
- 'a_week' => ':count semana',
-
- 'day' => ':count día',
- 'd' => ':count día',
- 'a_day' => ':count día',
-
- 'hour' => ':count reloch', // less reliable
- 'h' => ':count reloch', // less reliable
- 'a_hour' => ':count reloch', // less reliable
-
- 'minute' => ':count minuto',
- 'min' => ':count minuto',
- 'a_minute' => ':count minuto',
-
- 'second' => ':count segundo',
- 's' => ':count segundo',
- 'a_second' => ':count segundo',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/anp_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bhashaghar@googlegroups.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर"'],
- 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'],
- 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'],
- 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
- 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Atef Ben Ali (atefBB)
- * - Ibrahim AshShohail
- * - MLTDev
- * - Yazan Alnugnugh (yazan-alnugnugh)
- */
-$months = [
- 'يناير',
- 'فبراير',
- 'مارس',
- 'أبريل',
- 'مايو',
- 'يونيو',
- 'يوليو',
- 'أغسطس',
- 'سبتمبر',
- 'أكتوبر',
- 'نوفمبر',
- 'ديسمبر',
-];
-
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'a_second' => implode('|', ['{1}'.'بضع ثواني', 'ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => ':time من الآن',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم عند الساعة] LT',
- 'nextDay' => '[غدًا عند الساعة] LT',
- 'nextWeek' => 'dddd [عند الساعة] LT',
- 'lastDay' => '[أمس عند الساعة] LT',
- 'lastWeek' => 'dddd [عند الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
- 'months' => $months,
- 'months_short' => $months,
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'list' => ['، ', ' و '],
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت '],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Noureddine LOUAHEDJ
- * - JD Isaacks
- * - Atef Ben Ali (atefBB)
- */
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => 'في :time',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم على الساعة] LT',
- 'nextDay' => '[غدا على الساعة] LT',
- 'nextWeek' => 'dddd [على الساعة] LT',
- 'lastDay' => '[أمس على الساعة] LT',
- 'lastWeek' => 'dddd [على الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'months' => ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['احد', 'اثنين', 'ثلاثاء', 'اربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['أح', 'إث', 'ثلا', 'أر', 'خم', 'جم', 'سب'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 4,
- 'list' => ['، ', ' و '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Nusret Parlak
- * - JD Isaacks
- * - Atef Ben Ali (atefBB)
- */
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => 'في :time',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم على الساعة] LT',
- 'nextDay' => '[غدا على الساعة] LT',
- 'nextWeek' => 'dddd [على الساعة] LT',
- 'lastDay' => '[أمس على الساعة] LT',
- 'lastWeek' => 'dddd [على الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر'],
- 'months_short' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['احد', 'اثنين', 'ثلاثاء', 'اربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'list' => ['، ', ' و '],
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Atef Ben Ali (atefBB)
- * - Ibrahim AshShohail
- * - MLTDev
- */
-$months = [
- 'يناير',
- 'فبراير',
- 'مارس',
- 'أبريل',
- 'مايو',
- 'يونيو',
- 'يوليو',
- 'أغسطس',
- 'سبتمبر',
- 'أكتوبر',
- 'نوفمبر',
- 'ديسمبر',
-];
-
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => ':time من الآن',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم عند الساعة] LT',
- 'nextDay' => '[غدًا عند الساعة] LT',
- 'nextWeek' => 'dddd [عند الساعة] LT',
- 'lastDay' => '[أمس عند الساعة] LT',
- 'lastWeek' => 'dddd [عند الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'months' => $months,
- 'months_short' => $months,
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'list' => ['، ', ' و '],
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- * - Atef Ben Ali (atefBB)
- */
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => 'في :time',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم على الساعة] LT',
- 'nextDay' => '[غدا على الساعة] LT',
- 'nextWeek' => 'dddd [على الساعة] LT',
- 'lastDay' => '[أمس على الساعة] LT',
- 'lastWeek' => 'dddd [على الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر'],
- 'months_short' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['احد', 'اثنين', 'ثلاثاء', 'اربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'list' => ['، ', ' و '],
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- * - Atef Ben Ali (atefBB)
- */
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => 'في :time',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم على الساعة] LT',
- 'nextDay' => '[غدا على الساعة] LT',
- 'nextWeek' => 'dddd [على الساعة] LT',
- 'lastDay' => '[أمس على الساعة] LT',
- 'lastWeek' => 'dddd [على الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'list' => ['، ', ' و '],
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Abdellah Chadidi
- * - Atef Ben Ali (atefBB)
- */
-// Same for long and short
-$months = [
- // @TODO add shakl to months
- 'يناير',
- 'فبراير',
- 'مارس',
- 'أبريل',
- 'مايو',
- 'يونيو',
- 'يوليو',
- 'أغسطس',
- 'سبتمبر',
- 'أكتوبر',
- 'نوفمبر',
- 'ديسمبر',
-];
-
-return [
- 'year' => implode('|', ['سَنَة', 'سَنَة', 'سَنَتَيْن', 'سَنَوَات'.' :count', 'سَنَة'.' :count']),
- 'month' => implode('|', ['شَهْرَ', 'شَهْرَ', 'شَهْرَيْن', 'أَشْهُر'.' :count', 'شَهْرَ'.' :count']),
- 'week' => implode('|', ['أُسْبُوع', 'أُسْبُوع', 'أُسْبُوعَيْن', 'أَسَابِيع'.' :count', 'أُسْبُوع'.' :count']),
- 'day' => implode('|', ['يَوْم', 'يَوْم', 'يَوْمَيْن', 'أَيَّام'.' :count', 'يَوْم'.' :count']),
- 'hour' => implode('|', ['سَاعَة', 'سَاعَة', 'سَاعَتَيْن', 'سَاعَات'.' :count', 'سَاعَة'.' :count']),
- 'minute' => implode('|', ['دَقِيقَة', 'دَقِيقَة', 'دَقِيقَتَيْن', 'دَقَائِق'.' :count', 'دَقِيقَة'.' :count']),
- 'second' => implode('|', ['ثَانِيَة', 'ثَانِيَة', 'ثَانِيَتَيْن', 'ثَوَان'.' :count', 'ثَانِيَة'.' :count']),
- 'ago' => 'مُنْذُ :time',
- 'from_now' => 'مِنَ الْآن :time',
- 'after' => 'بَعْدَ :time',
- 'before' => 'قَبْلَ :time',
-
- // @TODO add shakl to translations below
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم عند الساعة] LT',
- 'nextDay' => '[غدًا عند الساعة] LT',
- 'nextWeek' => 'dddd [عند الساعة] LT',
- 'lastDay' => '[أمس عند الساعة] LT',
- 'lastWeek' => 'dddd [عند الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'months' => $months,
- 'months_short' => $months,
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'list' => ['، ', ' و '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - JD Isaacks
- * - Atef Ben Ali (atefBB)
- */
-return [
- 'year' => implode('|', ['سنة', 'سنة', 'سنتين', 'سنوات'.' :count', 'سنة'.' :count']),
- 'month' => implode('|', ['شهر', 'شهر', 'شهرين', 'أشهر'.' :count', 'شهر'.' :count']),
- 'week' => implode('|', ['أسبوع', 'أسبوع', 'أسبوعين', 'أسابيع'.' :count', 'أسبوع'.' :count']),
- 'day' => implode('|', ['يوم', 'يوم', 'يومين', 'أيام'.' :count', 'يوم'.' :count']),
- 'hour' => implode('|', ['ساعة', 'ساعة', 'ساعتين', 'ساعات'.' :count', 'ساعة'.' :count']),
- 'minute' => implode('|', ['دقيقة', 'دقيقة', 'دقيقتين', 'دقائق'.' :count', 'دقيقة'.' :count']),
- 'second' => implode('|', ['ثانية', 'ثانية', 'ثانيتين', 'ثوان'.' :count', 'ثانية'.' :count']),
- 'ago' => 'منذ :time',
- 'from_now' => 'في :time',
- 'after' => 'بعد :time',
- 'before' => 'قبل :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اليوم على الساعة] LT',
- 'nextDay' => '[غدا على الساعة] LT',
- 'nextWeek' => 'dddd [على الساعة] LT',
- 'lastDay' => '[أمس على الساعة] LT',
- 'lastWeek' => 'dddd [على الساعة] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ص', 'م'],
- 'months' => ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => ['، ', ' و '],
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ar.php', [
- 'formats' => [
- 'L' => 'DD MMM, YYYY',
- ],
- 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
- 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
- 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
- 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/as_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Amitakhya Phukan, Red Hat bug-glibc@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D-MM-YYYY',
- ],
- 'months' => ['জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ', 'নৱেম্বৰ', 'ডিচেম্বৰ'],
- 'months_short' => ['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
- 'weekdays' => ['দেওবাৰ', 'সোমবাৰ', 'মঙ্গলবাৰ', 'বুধবাৰ', 'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ', 'শনিবাৰ'],
- 'weekdays_short' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
- 'weekdays_min' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['পূৰ্ব্বাহ্ন', 'অপৰাহ্ন'],
-
- 'year' => ':count বছৰ',
- 'y' => ':count বছৰ',
- 'a_year' => ':count বছৰ',
-
- 'month' => ':count মাহ',
- 'm' => ':count মাহ',
- 'a_month' => ':count মাহ',
-
- 'week' => ':count সপ্তাহ',
- 'w' => ':count সপ্তাহ',
- 'a_week' => ':count সপ্তাহ',
-
- 'day' => ':count বাৰ',
- 'd' => ':count বাৰ',
- 'a_day' => ':count বাৰ',
-
- 'hour' => ':count ঘণ্টা',
- 'h' => ':count ঘণ্টা',
- 'a_hour' => ':count ঘণ্টা',
-
- 'minute' => ':count মিনিট',
- 'min' => ':count মিনিট',
- 'a_minute' => ':count মিনিট',
-
- 'second' => ':count দ্বিতীয়',
- 's' => ':count দ্বিতীয়',
- 'a_second' => ':count দ্বিতীয়',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['icheheavo', 'ichamthi'],
- 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
- 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Dec'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ast_ES.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Jordi Mallach jordi@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['de xineru', 'de febreru', 'de marzu', 'd’abril', 'de mayu', 'de xunu', 'de xunetu', 'd’agostu', 'de setiembre', 'd’ochobre', 'de payares', 'd’avientu'],
- 'months_short' => ['xin', 'feb', 'mar', 'abr', 'may', 'xun', 'xnt', 'ago', 'set', 'och', 'pay', 'avi'],
- 'weekdays' => ['domingu', 'llunes', 'martes', 'miércoles', 'xueves', 'vienres', 'sábadu'],
- 'weekdays_short' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'],
- 'weekdays_min' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count añu',
- 'y' => ':count añu',
- 'a_year' => ':count añu',
-
- 'month' => ':count mes',
- 'm' => ':count mes',
- 'a_month' => ':count mes',
-
- 'week' => ':count selmana',
- 'w' => ':count selmana',
- 'a_week' => ':count selmana',
-
- 'day' => ':count día',
- 'd' => ':count día',
- 'a_day' => ':count día',
-
- 'hour' => ':count hora',
- 'h' => ':count hora',
- 'a_hour' => ':count hora',
-
- 'minute' => ':count minutu',
- 'min' => ':count minutu',
- 'a_minute' => ':count minutu',
-
- 'second' => ':count segundu',
- 's' => ':count segundu',
- 'a_second' => ':count segundu',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ayc_PE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - runasimipi.org libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['inïru', 'phiwriru', 'marsu', 'awrila', 'mayu', 'junyu', 'julyu', 'awustu', 'sitimri', 'uktuwri', 'nuwimri', 'risimri'],
- 'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'jun', 'jul', 'awu', 'sit', 'ukt', 'nuw', 'ris'],
- 'weekdays' => ['tuminku', 'lunisa', 'martisa', 'mirkulisa', 'juywisa', 'wirnisa', 'sawäru'],
- 'weekdays_short' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'],
- 'weekdays_min' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['VM', 'NM'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Josh Soref
- * - Kunal Marwaha
- * - François B
- * - JD Isaacks
- * - Orxan
- * - Şəhriyar İmanov
- * - Baran Şengül
- */
-return [
- 'year' => ':count il',
- 'a_year' => '{1}bir il|]1,Inf[:count il',
- 'y' => ':count il',
- 'month' => ':count ay',
- 'a_month' => '{1}bir ay|]1,Inf[:count ay',
- 'm' => ':count ay',
- 'week' => ':count həftə',
- 'a_week' => '{1}bir həftə|]1,Inf[:count həftə',
- 'w' => ':count h.',
- 'day' => ':count gün',
- 'a_day' => '{1}bir gün|]1,Inf[:count gün',
- 'd' => ':count g.',
- 'hour' => ':count saat',
- 'a_hour' => '{1}bir saat|]1,Inf[:count saat',
- 'h' => ':count saat',
- 'minute' => ':count d.',
- 'a_minute' => '{1}bir dəqiqə|]1,Inf[:count dəqiqə',
- 'min' => ':count dəqiqə',
- 'second' => ':count san.',
- 'a_second' => '{1}birneçə saniyə|]1,Inf[:count saniyə',
- 's' => ':count saniyə',
- 'ago' => ':time əvvəl',
- 'from_now' => ':time sonra',
- 'after' => ':time sonra',
- 'before' => ':time əvvəl',
- 'diff_now' => 'indi',
- 'diff_yesterday' => 'dünən',
- 'diff_tomorrow' => 'sabah',
- 'diff_before_yesterday' => 'srağagün',
- 'diff_after_tomorrow' => 'birisi gün',
- 'period_recurrences' => ':count dəfədən bir',
- 'period_interval' => 'hər :interval',
- 'period_start_date' => ':date tarixindən başlayaraq',
- 'period_end_date' => ':date tarixinədək',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[bugün saat] LT',
- 'nextDay' => '[sabah saat] LT',
- 'nextWeek' => '[gələn həftə] dddd [saat] LT',
- 'lastDay' => '[dünən] LT',
- 'lastWeek' => '[keçən həftə] dddd [saat] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- if ($number === 0) { // special case for zero
- return "$number-ıncı";
- }
-
- static $suffixes = [
- 1 => '-inci',
- 5 => '-inci',
- 8 => '-inci',
- 70 => '-inci',
- 80 => '-inci',
- 2 => '-nci',
- 7 => '-nci',
- 20 => '-nci',
- 50 => '-nci',
- 3 => '-üncü',
- 4 => '-üncü',
- 100 => '-üncü',
- 6 => '-ncı',
- 9 => '-uncu',
- 10 => '-uncu',
- 30 => '-uncu',
- 60 => '-ıncı',
- 90 => '-ıncı',
- ];
-
- $lastDigit = $number % 10;
-
- return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
- },
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'gecə';
- }
- if ($hour < 12) {
- return 'səhər';
- }
- if ($hour < 17) {
- return 'gündüz';
- }
-
- return 'axşam';
- },
- 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
- 'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],
- 'months_standalone' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'],
- 'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
- 'weekdays_short' => ['baz', 'bze', 'çax', 'çər', 'cax', 'cüm', 'şən'],
- 'weekdays_min' => ['bz', 'be', 'ça', 'çə', 'ca', 'cü', 'şə'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' və '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Pablo Saratxaga pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/az.php', [
- 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
- 'weekdays' => ['bazar günü', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
- 'weekdays_short' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'],
- 'weekdays_min' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/az.php', [
- 'weekdays' => ['базар', 'базар ертәси', 'чәршәнбә ахшамы', 'чәршәнбә', 'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
- 'weekdays_short' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'],
- 'weekdays_min' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'],
- 'months' => ['јанвар', 'феврал', 'март', 'апрел', 'май', 'ијун', 'ијул', 'август', 'сентјабр', 'октјабр', 'нојабр', 'декабр'],
- 'months_short' => ['јан', 'фев', 'мар', 'апр', 'май', 'ијн', 'ијл', 'авг', 'сен', 'окт', 'ној', 'дек'],
- 'months_standalone' => ['Јанвар', 'Феврал', 'Март', 'Апрел', 'Май', 'Ијун', 'Ијул', 'Август', 'Сентјабр', 'Октјабр', 'Нојабр', 'Декабр'],
- 'meridiem' => ['а', 'п'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Mousa Moradi mousamk@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'OY/OM/OD',
- ],
- 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
- 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
- 'weekdays' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
- 'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
- 'weekdays_min' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
- 'first_day_of_week' => 6,
- 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/az.php', [
- 'meridiem' => ['a', 'p'],
- 'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
- 'weekdays_short' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
- 'weekdays_min' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
- 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
- 'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],
- 'months_standalone' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'D MMMM YYYY, dddd HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['I bikɛ̂glà', 'I ɓugajɔp'],
- 'weekdays' => ['ŋgwà nɔ̂y', 'ŋgwà njaŋgumba', 'ŋgwà ûm', 'ŋgwà ŋgê', 'ŋgwà mbɔk', 'ŋgwà kɔɔ', 'ŋgwà jôn'],
- 'weekdays_short' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
- 'weekdays_min' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
- 'months' => ['Kɔndɔŋ', 'Màcɛ̂l', 'Màtùmb', 'Màtop', 'M̀puyɛ', 'Hìlòndɛ̀', 'Njèbà', 'Hìkaŋ', 'Dìpɔ̀s', 'Bìòôm', 'Màyɛsèp', 'Lìbuy li ńyèe'],
- 'months_short' => ['kɔn', 'mac', 'mat', 'mto', 'mpu', 'hil', 'nje', 'hik', 'dip', 'bio', 'may', 'liɓ'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'second' => ':count móndî', // less reliable
- 's' => ':count móndî', // less reliable
- 'a_second' => ':count móndî', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
-}, 'be');
-
-/*
- * Authors:
- * - Josh Soref
- * - SobakaSlava
- * - François B
- * - Serhan Apaydın
- * - JD Isaacks
- */
-return [
- 'year' => ':count год|:count гады|:count гадоў',
- 'y' => ':count год|:count гады|:count гадоў',
- 'month' => ':count месяц|:count месяцы|:count месяцаў',
- 'm' => ':count месяц|:count месяцы|:count месяцаў',
- 'week' => ':count тыдзень|:count тыдні|:count тыдняў',
- 'w' => ':count тыдзень|:count тыдні|:count тыдняў',
- 'day' => ':count дзень|:count ні|:count дзён',
- 'd' => ':count дзень|:count ні|:count дзён',
- 'hour' => ':count гадзіну|:count гадзіны|:count гадзін',
- 'h' => ':count гадзіну|:count гадзіны|:count гадзін',
- 'minute' => ':count хвіліну|:count хвіліны|:count хвілін',
- 'min' => ':count хвіліну|:count хвіліны|:count хвілін',
- 'second' => ':count секунду|:count секунды|:count секунд',
- 's' => ':count секунду|:count секунды|:count секунд',
- 'ago' => ':time таму',
- 'from_now' => 'праз :time',
- 'after' => ':time пасля',
- 'before' => ':time да',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY г.',
- 'LLL' => 'D MMMM YYYY г., HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY г., HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Сёння ў] LT',
- 'nextDay' => '[Заўтра ў] LT',
- 'nextWeek' => '[У] dddd [ў] LT',
- 'lastDay' => '[Учора ў] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- switch ($current->dayOfWeek) {
- case 1:
- case 2:
- case 4:
- return '[У мінулы] dddd [ў] LT';
- default:
- return '[У мінулую] dddd [ў] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'M':
- case 'd':
- case 'DDD':
- case 'w':
- case 'W':
- return ($number % 10 === 2 || $number % 10 === 3) && ($number % 100 !== 12 && $number % 100 !== 13) ? $number.'-і' : $number.'-ы';
- case 'D':
- return $number.'-га';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'ночы';
- }
- if ($hour < 12) {
- return 'раніцы';
- }
- if ($hour < 17) {
- return 'дня';
- }
-
- return 'вечара';
- },
- 'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'траўня', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'],
- 'months_standalone' => ['студзень', 'люты', 'сакавік', 'красавік', 'травень', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'],
- 'months_short' => ['студ', 'лют', 'сак', 'крас', 'трав', 'чэрв', 'ліп', 'жнів', 'вер', 'каст', 'ліст', 'снеж'],
- 'months_regexp' => '/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => ['нядзелю', 'панядзелак', 'аўторак', 'сераду', 'чацвер', 'пятніцу', 'суботу'],
- 'weekdays_standalone' => ['нядзеля', 'панядзелак', 'аўторак', 'серада', 'чацвер', 'пятніца', 'субота'],
- 'weekdays_short' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],
- 'weekdays_min' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],
- 'weekdays_regexp' => '/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' і '],
- 'months_short_standalone' => ['сту', 'лют', 'сак', 'кра', 'май', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/be.php', [
- 'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'мая', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'],
- 'months_short' => ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
- 'weekdays' => ['Нядзеля', 'Панядзелак', 'Аўторак', 'Серада', 'Чацвер', 'Пятніца', 'Субота'],
- 'weekdays_short' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'],
- 'weekdays_min' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['studzienia', 'lutaha', 'sakavika', 'krasavika', 'maja', 'červienia', 'lipienia', 'žniŭnia', 'vieraśnia', 'kastryčnika', 'listapada', 'śniežnia'],
- 'months_short' => ['Stu', 'Lut', 'Sak', 'Kra', 'Maj', 'Čer', 'Lip', 'Žni', 'Vie', 'Kas', 'Lis', 'Śni'],
- 'weekdays' => ['Niadziela', 'Paniadziełak', 'Aŭtorak', 'Sierada', 'Čaćvier', 'Piatnica', 'Subota'],
- 'weekdays_short' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'],
- 'weekdays_min' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/bem_ZM.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - ANLoc Martin Benjamin locales@africanlocalization.net
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'MM/DD/YYYY',
- ],
- 'months' => ['Januari', 'Februari', 'Machi', 'Epreo', 'Mei', 'Juni', 'Julai', 'Ogasti', 'Septemba', 'Oktoba', 'Novemba', 'Disemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Epr', 'Mei', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Dis'],
- 'weekdays' => ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu', 'Palichine', 'Palichisano', 'Pachibelushi'],
- 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- 'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['uluchelo', 'akasuba'],
-
- 'year' => 'myaka :count',
- 'y' => 'myaka :count',
- 'a_year' => 'myaka :count',
-
- 'month' => 'myeshi :count',
- 'm' => 'myeshi :count',
- 'a_month' => 'myeshi :count',
-
- 'week' => 'umulungu :count',
- 'w' => 'umulungu :count',
- 'a_week' => 'umulungu :count',
-
- 'day' => 'inshiku :count',
- 'd' => 'inshiku :count',
- 'a_day' => 'inshiku :count',
-
- 'hour' => 'awala :count',
- 'h' => 'awala :count',
- 'a_hour' => 'awala :count',
-
- 'minute' => 'miniti :count',
- 'min' => 'miniti :count',
- 'a_minute' => 'miniti :count',
-
- 'second' => 'sekondi :count',
- 's' => 'sekondi :count',
- 'a_second' => 'sekondi :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ber_DZ.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Pablo Saratxaga pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
- 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
- 'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'],
- 'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
- 'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Pablo Saratxaga pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
- 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
- 'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'],
- 'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
- 'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['pamilau', 'pamunyi'],
- 'weekdays' => ['pa mulungu', 'pa shahuviluha', 'pa hivili', 'pa hidatu', 'pa hitayi', 'pa hihanu', 'pa shahulembela'],
- 'weekdays_short' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
- 'weekdays_min' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
- 'months' => ['pa mwedzi gwa hutala', 'pa mwedzi gwa wuvili', 'pa mwedzi gwa wudatu', 'pa mwedzi gwa wutai', 'pa mwedzi gwa wuhanu', 'pa mwedzi gwa sita', 'pa mwedzi gwa saba', 'pa mwedzi gwa nane', 'pa mwedzi gwa tisa', 'pa mwedzi gwa kumi', 'pa mwedzi gwa kumi na moja', 'pa mwedzi gwa kumi na mbili'],
- 'months_short' => ['Hut', 'Vil', 'Dat', 'Tai', 'Han', 'Sit', 'Sab', 'Nan', 'Tis', 'Kum', 'Kmj', 'Kmb'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - Serhan Apaydın
- * - JD Isaacks
- * - Glavić
- */
-return [
- 'year' => ':count година|:count години',
- 'a_year' => 'година|:count години',
- 'y' => ':count година|:count години',
- 'month' => ':count месец|:count месеца',
- 'a_month' => 'месец|:count месеца',
- 'm' => ':count месец|:count месеца',
- 'week' => ':count седмица|:count седмици',
- 'a_week' => 'седмица|:count седмици',
- 'w' => ':count седмица|:count седмици',
- 'day' => ':count ден|:count дни',
- 'a_day' => 'ден|:count дни',
- 'd' => ':count ден|:count дни',
- 'hour' => ':count час|:count часа',
- 'a_hour' => 'час|:count часа',
- 'h' => ':count час|:count часа',
- 'minute' => ':count минута|:count минути',
- 'a_minute' => 'минута|:count минути',
- 'min' => ':count минута|:count минути',
- 'second' => ':count секунда|:count секунди',
- 'a_second' => 'няколко секунди|:count секунди',
- 's' => ':count секунда|:count секунди',
- 'ago' => 'преди :time',
- 'from_now' => 'след :time',
- 'after' => 'след :time',
- 'before' => 'преди :time',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'D.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Днес в] LT',
- 'nextDay' => '[Утре в] LT',
- 'nextWeek' => 'dddd [в] LT',
- 'lastDay' => '[Вчера в] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- switch ($current->dayOfWeek) {
- case 0:
- case 3:
- case 6:
- return '[В изминалата] dddd [в] LT';
- default:
- return '[В изминалия] dddd [в] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- $lastDigit = $number % 10;
- $last2Digits = $number % 100;
- if ($number === 0) {
- return "$number-ев";
- }
- if ($last2Digits === 0) {
- return "$number-ен";
- }
- if ($last2Digits > 10 && $last2Digits < 20) {
- return "$number-ти";
- }
- if ($lastDigit === 1) {
- return "$number-ви";
- }
- if ($lastDigit === 2) {
- return "$number-ри";
- }
- if ($lastDigit === 7 || $lastDigit === 8) {
- return "$number-ми";
- }
-
- return "$number-ти";
- },
- 'months' => ['януари', 'февруари', 'март', 'април', 'май', 'юни', 'юли', 'август', 'септември', 'октомври', 'ноември', 'декември'],
- 'months_short' => ['яну', 'фев', 'мар', 'апр', 'май', 'юни', 'юли', 'авг', 'сеп', 'окт', 'ное', 'дек'],
- 'weekdays' => ['неделя', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота'],
- 'weekdays_short' => ['нед', 'пон', 'вто', 'сря', 'чет', 'пет', 'съб'],
- 'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' и '],
- 'meridiem' => ['преди обяд', 'следобед'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/bg.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/bhb_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Samsung Electronics Co., Ltd. alexey.merzlyakov@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- 'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
- 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- 'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/bho_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bhashaghar@googlegroups.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'],
- 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'],
- 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],
- 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
- 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-
- 'hour' => ':count मौसम',
- 'h' => ':count मौसम',
- 'a_hour' => ':count मौसम',
-
- 'minute' => ':count कला',
- 'min' => ':count कला',
- 'a_minute' => ':count कला',
-
- 'second' => ':count सोमार',
- 's' => ':count सोमार',
- 'a_second' => ':count सोमार',
-
- 'year' => ':count साल',
- 'y' => ':count साल',
- 'a_year' => ':count साल',
-
- 'month' => ':count महिना',
- 'm' => ':count महिना',
- 'a_month' => ':count महिना',
-
- 'week' => ':count सप्ताह',
- 'w' => ':count सप्ताह',
- 'a_week' => ':count सप्ताह',
-
- 'day' => ':count दिन',
- 'd' => ':count दिन',
- 'a_day' => ':count दिन',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/bi_VU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com & maninder1.s@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'dddd DD MMM YYYY',
- ],
- 'months' => ['jenuware', 'febwari', 'maj', 'epril', 'mei', 'jun', 'julae', 'ogis', 'septemba', 'oktoba', 'novemba', 'disemba'],
- 'months_short' => ['jen', 'feb', 'maj', 'epr', 'mei', 'jun', 'jul', 'ogi', 'sep', 'okt', 'nov', 'dis'],
- 'weekdays' => ['sande', 'mande', 'maj', 'wota', 'fraede', 'sarede'],
- 'weekdays_short' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'],
- 'weekdays_min' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'],
-
- 'year' => ':count seven', // less reliable
- 'y' => ':count seven', // less reliable
- 'a_year' => ':count seven', // less reliable
-
- 'month' => ':count mi', // less reliable
- 'm' => ':count mi', // less reliable
- 'a_month' => ':count mi', // less reliable
-
- 'week' => ':count sarede', // less reliable
- 'w' => ':count sarede', // less reliable
- 'a_week' => ':count sarede', // less reliable
-
- 'day' => ':count betde', // less reliable
- 'd' => ':count betde', // less reliable
- 'a_day' => ':count betde', // less reliable
-
- 'hour' => ':count klok', // less reliable
- 'h' => ':count klok', // less reliable
- 'a_hour' => ':count klok', // less reliable
-
- 'minute' => ':count smol', // less reliable
- 'min' => ':count smol', // less reliable
- 'a_minute' => ':count smol', // less reliable
-
- 'second' => ':count tu', // less reliable
- 's' => ':count tu', // less reliable
- 'a_second' => ':count tu', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'bm');
-
-/*
- * Authors:
- * - Estelle Comment
- */
-return [
- 'year' => 'san :count',
- 'a_year' => 'san kelen|san :count',
- 'y' => 'san :count',
- 'month' => 'kalo :count',
- 'a_month' => 'kalo kelen|kalo :count',
- 'm' => 'k. :count',
- 'week' => 'dɔgɔkun :count',
- 'a_week' => 'dɔgɔkun kelen',
- 'w' => 'd. :count',
- 'day' => 'tile :count',
- 'd' => 't. :count',
- 'a_day' => 'tile kelen|tile :count',
- 'hour' => 'lɛrɛ :count',
- 'a_hour' => 'lɛrɛ kelen|lɛrɛ :count',
- 'h' => 'l. :count',
- 'minute' => 'miniti :count',
- 'a_minute' => 'miniti kelen|miniti :count',
- 'min' => 'm. :count',
- 'second' => 'sekondi :count',
- 'a_second' => 'sanga dama dama|sekondi :count',
- 's' => 'sek. :count',
- 'ago' => 'a bɛ :time bɔ',
- 'from_now' => ':time kɔnɔ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'MMMM [tile] D [san] YYYY',
- 'LLL' => 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
- 'LLLL' => 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Bi lɛrɛ] LT',
- 'nextDay' => '[Sini lɛrɛ] LT',
- 'nextWeek' => 'dddd [don lɛrɛ] LT',
- 'lastDay' => '[Kunu lɛrɛ] LT',
- 'lastWeek' => 'dddd [tɛmɛnen lɛrɛ] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['Zanwuyekalo', 'Fewuruyekalo', 'Marisikalo', 'Awirilikalo', 'Mɛkalo', 'Zuwɛnkalo', 'Zuluyekalo', 'Utikalo', 'Sɛtanburukalo', 'ɔkutɔburukalo', 'Nowanburukalo', 'Desanburukalo'],
- 'months_short' => ['Zan', 'Few', 'Mar', 'Awi', 'Mɛ', 'Zuw', 'Zul', 'Uti', 'Sɛt', 'ɔku', 'Now', 'Des'],
- 'weekdays' => ['Kari', 'Ntɛnɛn', 'Tarata', 'Araba', 'Alamisa', 'Juma', 'Sibiri'],
- 'weekdays_short' => ['Kar', 'Ntɛ', 'Tar', 'Ara', 'Ala', 'Jum', 'Sib'],
- 'weekdays_min' => ['Ka', 'Nt', 'Ta', 'Ar', 'Al', 'Ju', 'Si'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' ni '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Shakib Hossain
- * - Raju
- * - Aniruddha Adhikary
- * - JD Isaacks
- * - Saiful Islam
- * - Faisal Islam
- */
-return [
- 'year' => ':count বছর',
- 'a_year' => 'এক বছর|:count বছর',
- 'y' => '১ বছর|:count বছর',
- 'month' => ':count মাস',
- 'a_month' => 'এক মাস|:count মাস',
- 'm' => '১ মাস|:count মাস',
- 'week' => ':count সপ্তাহ',
- 'a_week' => '১ সপ্তাহ|:count সপ্তাহ',
- 'w' => '১ সপ্তাহ|:count সপ্তাহ',
- 'day' => ':count দিন',
- 'a_day' => 'এক দিন|:count দিন',
- 'd' => '১ দিন|:count দিন',
- 'hour' => ':count ঘন্টা',
- 'a_hour' => 'এক ঘন্টা|:count ঘন্টা',
- 'h' => '১ ঘন্টা|:count ঘন্টা',
- 'minute' => ':count মিনিট',
- 'a_minute' => 'এক মিনিট|:count মিনিট',
- 'min' => '১ মিনিট|:count মিনিট',
- 'second' => ':count সেকেন্ড',
- 'a_second' => 'কয়েক সেকেন্ড|:count সেকেন্ড',
- 's' => '১ সেকেন্ড|:count সেকেন্ড',
- 'ago' => ':time আগে',
- 'from_now' => ':time পরে',
- 'after' => ':time পরে',
- 'before' => ':time আগে',
- 'diff_now' => 'এখন',
- 'diff_yesterday' => 'গতকাল',
- 'diff_tomorrow' => 'আগামীকাল',
- 'period_recurrences' => ':count বার|:count বার',
- 'period_interval' => 'প্রতি :interval',
- 'period_start_date' => ':date থেকে',
- 'period_end_date' => ':date পর্যন্ত',
- 'formats' => [
- 'LT' => 'A Oh:Om সময়',
- 'LTS' => 'A Oh:Om:Os সময়',
- 'L' => 'OD/OM/OY',
- 'LL' => 'OD MMMM OY',
- 'LLL' => 'OD MMMM OY, A Oh:Om সময়',
- 'LLLL' => 'dddd, OD MMMM OY, A Oh:Om সময়',
- ],
- 'calendar' => [
- 'sameDay' => '[আজ] LT',
- 'nextDay' => '[আগামীকাল] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[গতকাল] LT',
- 'lastWeek' => '[গত] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'রাত';
- }
- if ($hour < 10) {
- return 'সকাল';
- }
- if ($hour < 17) {
- return 'দুপুর';
- }
- if ($hour < 20) {
- return 'বিকাল';
- }
-
- return 'রাত';
- },
- 'months' => ['জানুয়ারী', 'ফেব্রুয়ারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
- 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্র', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
- 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
- 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
- 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গ', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
- 'list' => [', ', ' এবং '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'weekdays_standalone' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহষ্পতিবার', 'শুক্রবার', 'শনিবার'],
- 'weekdays_min_standalone' => ['রঃ', 'সোঃ', 'মঃ', 'বুঃ', 'বৃঃ', 'শুঃ', 'শনি'],
- 'months_short_standalone' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
- 'alt_numbers' => ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ankur Group, http://www.ankurbangla.org, http://www.bengalinux.org Taneem Ahmed, Jamil Ahmed taneem@bengalinux.org, jamil@bengalinux.org
- */
-return array_replace_recursive(require __DIR__.'/bn.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
- 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
- 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
- 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
- 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
- 'first_day_of_week' => 5,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/bn.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
- 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
- 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
- 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
- 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- */
-return [
- 'year' => '{1}ལོ་གཅིག|]1,Inf[:count ལོ',
- 'month' => '{1}ཟླ་བ་གཅིག|]1,Inf[:count ཟླ་བ',
- 'week' => ':count བདུན་ཕྲག',
- 'day' => '{1}ཉིན་གཅིག|]1,Inf[:count ཉིན་',
- 'hour' => '{1}ཆུ་ཚོད་གཅིག|]1,Inf[:count ཆུ་ཚོད',
- 'minute' => '{1}སྐར་མ་གཅིག|]1,Inf[:count སྐར་མ',
- 'second' => '{1}ལམ་སང|]1,Inf[:count སྐར་ཆ།',
- 'ago' => ':time སྔན་ལ',
- 'from_now' => ':time ལ་',
- 'diff_yesterday' => 'ཁ་སང',
- 'diff_tomorrow' => 'སང་ཉིན',
- 'formats' => [
- 'LT' => 'A h:mm',
- 'LTS' => 'A h:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[དི་རིང] LT',
- 'nextDay' => '[སང་ཉིན] LT',
- 'nextWeek' => '[བདུན་ཕྲག་རྗེས་མ], LT',
- 'lastDay' => '[ཁ་སང] LT',
- 'lastWeek' => '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'མཚན་མོ';
- }
- if ($hour < 10) {
- return 'ཞོགས་ཀས';
- }
- if ($hour < 17) {
- return 'ཉིན་གུང';
- }
- if ($hour < 20) {
- return 'དགོང་དག';
- }
-
- return 'མཚན་མོ';
- },
- 'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
- 'months_short' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
- 'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
- 'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'],
- 'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'],
- 'list' => [', ', ' ཨནད་ '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/bo.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/bo.php', [
- 'meridiem' => ['སྔ་དྲོ་', 'ཕྱི་དྲོ་'],
- 'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
- 'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'],
- 'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'],
- 'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
- 'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
- 'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
- 'weekend' => [0, 0],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'YYYY ལོའི་MMMཚེས་D',
- 'LLL' => 'སྤྱི་ལོ་YYYY MMMMའི་ཚེས་D h:mm a',
- 'LLLL' => 'YYYY MMMMའི་ཚེས་D, dddd h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'br');
-
-/*
- * Authors:
- * - François B
- * - Serhan Apaydın
- * - JD Isaacks
- */
-return [
- 'year' => '{1}:count bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz',
- 'a_year' => '{1}ur bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz',
- 'month' => '{1}:count miz|{2}:count viz|[0,Inf[:count miz',
- 'a_month' => '{1}ur miz|{2}:count viz|[0,Inf[:count miz',
- 'week' => ':count sizhun',
- 'a_week' => 'ur sizhun|:count sizhun',
- 'day' => '{1}:count devezh|{2}:count zevezh|[0,Inf[:count devezh',
- 'a_day' => '{1}un devezh|{2}:count zevezh|[0,Inf[:count devezh',
- 'hour' => ':count eur',
- 'a_hour' => 'un eur|:count eur',
- 'minute' => '{1}:count vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn',
- 'a_minute' => '{1}ur vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn',
- 'second' => ':count eilenn',
- 'a_second' => '{1}un nebeud segondennoù|[0,Inf[:count eilenn',
- 'ago' => ':time \'zo',
- 'from_now' => 'a-benn :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D [a viz] MMMM YYYY',
- 'LLL' => 'D [a viz] MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D [a viz] MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Hiziv da] LT',
- 'nextDay' => '[Warc\'hoazh da] LT',
- 'nextWeek' => 'dddd [da] LT',
- 'lastDay' => '[Dec\'h da] LT',
- 'lastWeek' => 'dddd [paset da] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- return $number.($number === 1 ? 'añ' : 'vet');
- },
- 'months' => ['Genver', 'C\'hwevrer', 'Meurzh', 'Ebrel', 'Mae', 'Mezheven', 'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
- 'months_short' => ['Gen', 'C\'hwe', 'Meu', 'Ebr', 'Mae', 'Eve', 'Gou', 'Eos', 'Gwe', 'Her', 'Du', 'Ker'],
- 'weekdays' => ['Sul', 'Lun', 'Meurzh', 'Merc\'her', 'Yaou', 'Gwener', 'Sadorn'],
- 'weekdays_short' => ['Sul', 'Lun', 'Meu', 'Mer', 'Yao', 'Gwe', 'Sad'],
- 'weekdays_min' => ['Su', 'Lu', 'Me', 'Mer', 'Ya', 'Gw', 'Sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' hag '],
- 'meridiem' => ['A.M.', 'G.M.'],
-
- 'y' => ':count bl.',
- 'd' => ':count d',
- 'h' => ':count e',
- 'min' => ':count min',
- 's' => ':count s',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/br.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/brx_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'M/D/YY',
- ],
- 'months' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एफ्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'],
- 'months_short' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एप्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'],
- 'weekdays' => ['रबिबार', 'सोबार', 'मंगलबार', 'बुदबार', 'बिसथिबार', 'सुखुरबार', 'सुनिबार'],
- 'weekdays_short' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'],
- 'weekdays_min' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['फुं.', 'बेलासे.'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bokideckonja
- * - Josh Soref
- * - François B
- * - shaishavgandhi05
- * - Serhan Apaydın
- * - JD Isaacks
- */
-return [
- 'year' => ':count godina|:count godine|:count godina',
- 'y' => ':count godina|:count godine|:count godina',
- 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
- 'm' => ':count mjesec|:count mjeseca|:count mjeseci',
- 'week' => ':count nedjelja|:count nedjelje|:count nedjelja',
- 'w' => ':count nedjelja|:count nedjelje|:count nedjelja',
- 'day' => ':count dan|:count dana|:count dana',
- 'd' => ':count dan|:count dana|:count dana',
- 'hour' => ':count sat|:count sata|:count sati',
- 'h' => ':count sat|:count sata|:count sati',
- 'minute' => ':count minut|:count minuta|:count minuta',
- 'min' => ':count minut|:count minuta|:count minuta',
- 'second' => ':count sekund|:count sekunda|:count sekundi',
- 's' => ':count sekund|:count sekunda|:count sekundi',
- 'ago' => 'prije :time',
- 'from_now' => 'za :time',
- 'after' => 'nakon :time',
- 'before' => ':time ranije',
- 'diff_yesterday' => 'jučer',
- 'diff_tomorrow' => 'sutra',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[danas u] LT',
- 'nextDay' => '[sutra u] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $current) {
- switch ($current->dayOfWeek) {
- case 0:
- return '[u] [nedjelju] [u] LT';
- case 3:
- return '[u] [srijedu] [u] LT';
- case 6:
- return '[u] [subotu] [u] LT';
- default:
- return '[u] dddd [u] LT';
- }
- },
- 'lastDay' => '[jučer u] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- switch ($current->dayOfWeek) {
- case 0:
- case 3:
- return '[prošlu] dddd [u] LT';
- case 6:
- return '[prošle] [subote] [u] LT';
- default:
- return '[prošli] dddd [u] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
- 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj.', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'],
- 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
- 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
- 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' i '],
- 'meridiem' => ['prijepodne', 'popodne'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/bs.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/bs.php', [
- 'meridiem' => ['пре подне', 'поподне'],
- 'weekdays' => ['недјеља', 'понедјељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
- 'weekdays_short' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
- 'weekdays_min' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
- 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јуни', 'јули', 'аугуст', 'септембар', 'октобар', 'новембар', 'децембар'],
- 'months_short' => ['јан', 'феб', 'мар', 'апр', 'мај', 'јун', 'јул', 'ауг', 'сеп', 'окт', 'нов', 'дец'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D.M.YYYY.',
- 'LL' => 'DD.MM.YYYY.',
- 'LLL' => 'DD. MMMM YYYY. HH:mm',
- 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/bs.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/byn_ER.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ልደትሪ', 'ካብኽብቲ', 'ክብላ', 'ፋጅኺሪ', 'ክቢቅሪ', 'ምኪኤል ትጓ̅ኒሪ', 'ኰርኩ', 'ማርያም ትሪ', 'ያኸኒ መሳቅለሪ', 'መተሉ', 'ምኪኤል መሽወሪ', 'ተሕሳስሪ'],
- 'months_short' => ['ልደት', 'ካብኽ', 'ክብላ', 'ፋጅኺ', 'ክቢቅ', 'ም/ት', 'ኰር', 'ማርያ', 'ያኸኒ', 'መተሉ', 'ም/ም', 'ተሕሳ'],
- 'weekdays' => ['ሰንበር ቅዳዅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ ወሪ ለብዋ', 'ኣምድ', 'ኣርብ', 'ሰንበር ሽጓዅ'],
- 'weekdays_short' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'],
- 'weekdays_min' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ፋዱስ ጃብ', 'ፋዱስ ደምቢ'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - mestremuten
- * - François B
- * - Marc Ordinas i Llopis
- * - Pere Orga
- * - JD Isaacks
- * - Quentí
- * - Víctor Díaz
- * - Xavi
- * - qcardona
- */
-return [
- 'year' => ':count any|:count anys',
- 'a_year' => 'un any|:count anys',
- 'y' => ':count any|:count anys',
- 'month' => ':count mes|:count mesos',
- 'a_month' => 'un mes|:count mesos',
- 'm' => ':count mes|:count mesos',
- 'week' => ':count setmana|:count setmanes',
- 'a_week' => 'una setmana|:count setmanes',
- 'w' => ':count setmana|:count setmanes',
- 'day' => ':count dia|:count dies',
- 'a_day' => 'un dia|:count dies',
- 'd' => ':count d',
- 'hour' => ':count hora|:count hores',
- 'a_hour' => 'una hora|:count hores',
- 'h' => ':count h',
- 'minute' => ':count minut|:count minuts',
- 'a_minute' => 'un minut|:count minuts',
- 'min' => ':count min',
- 'second' => ':count segon|:count segons',
- 'a_second' => 'uns segons|:count segons',
- 's' => ':count s',
- 'ago' => 'fa :time',
- 'from_now' => 'd\'aquí :time',
- 'after' => ':time després',
- 'before' => ':time abans',
- 'diff_now' => 'ara mateix',
- 'diff_yesterday' => 'ahir',
- 'diff_tomorrow' => 'demà',
- 'diff_before_yesterday' => 'abans d\'ahir',
- 'diff_after_tomorrow' => 'demà passat',
- 'period_recurrences' => ':count cop|:count cops',
- 'period_interval' => 'cada :interval',
- 'period_start_date' => 'de :date',
- 'period_end_date' => 'fins a :date',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM [de] YYYY',
- 'LLL' => 'D MMMM [de] YYYY [a les] H:mm',
- 'LLLL' => 'dddd D MMMM [de] YYYY [a les] H:mm',
- ],
- 'calendar' => [
- 'sameDay' => function (\Carbon\CarbonInterface $current) {
- return '[avui a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
- },
- 'nextDay' => function (\Carbon\CarbonInterface $current) {
- return '[demà a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
- },
- 'nextWeek' => function (\Carbon\CarbonInterface $current) {
- return 'dddd [a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
- },
- 'lastDay' => function (\Carbon\CarbonInterface $current) {
- return '[ahir a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
- },
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- return '[el] dddd [passat a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- return $number.(
- ($period === 'w' || $period === 'W') ? 'a' : (
- ($number === 1) ? 'r' : (
- ($number === 2) ? 'n' : (
- ($number === 3) ? 'r' : (
- ($number === 4) ? 't' : 'è'
- )
- )
- )
- )
- );
- },
- 'months' => ['de gener', 'de febrer', 'de març', 'd\'abril', 'de maig', 'de juny', 'de juliol', 'd\'agost', 'de setembre', 'd\'octubre', 'de novembre', 'de desembre'],
- 'months_standalone' => ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
- 'months_short' => ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
- 'months_regexp' => '/D[oD]?[\s,]+MMMM?/',
- 'weekdays' => ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte'],
- 'weekdays_short' => ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
- 'weekdays_min' => ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' i '],
- 'meridiem' => ['a. m.', 'p. m.'],
- 'months_short_standalone' => ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ca.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ca.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ca.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ca.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ca.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['𑄢𑄧𑄝𑄨𑄝𑄢𑄴', '𑄥𑄧𑄟𑄴𑄝𑄢𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴𑄝𑄢𑄴', '𑄝𑄪𑄖𑄴𑄝𑄢𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴𑄝𑄢𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴𑄝𑄢𑄴', '𑄥𑄧𑄚𑄨𑄝𑄢𑄴'],
- 'weekdays_short' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'],
- 'weekdays_min' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'],
- 'months' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄬𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'],
- 'months_short' => ['𑄎𑄚𑄪', '𑄜𑄬𑄛𑄴', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄢𑄴'],
- 'months_short_standalone' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM, YYYY h:mm a',
- 'LLLL' => 'dddd, D MMMM, YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ccp.php', [
- 'weekend' => [0, 0],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ce_RU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - ANCHR
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY.DD.MM',
- ],
- 'months' => ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
- 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'weekdays' => ['КӀиранан де', 'Оршотан де', 'Шинарин де', 'Кхаарин де', 'Еарин де', 'ПӀераскан де', 'Шот де'],
- 'weekdays_short' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'],
- 'weekdays_min' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count шо',
- 'y' => ':count шо',
- 'a_year' => ':count шо',
-
- 'month' => ':count бутт',
- 'm' => ':count бутт',
- 'a_month' => ':count бутт',
-
- 'week' => ':count кӏира',
- 'w' => ':count кӏира',
- 'a_week' => ':count кӏира',
-
- 'day' => ':count де',
- 'd' => ':count де',
- 'a_day' => ':count де',
-
- 'hour' => ':count сахьт',
- 'h' => ':count сахьт',
- 'a_hour' => ':count сахьт',
-
- 'minute' => ':count минот',
- 'min' => ':count минот',
- 'a_minute' => ':count минот',
-
- 'second' => ':count секунд',
- 's' => ':count секунд',
- 'a_second' => ':count секунд',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'],
- 'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
- 'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
- 'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
- 'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'day' => ':count ruhanga', // less reliable
- 'd' => ':count ruhanga', // less reliable
- 'a_day' => ':count ruhanga', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/chr_US.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Cherokee Nation Joseph Erb josepherb7@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'MM/DD/YYYY',
- ],
- 'months' => ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ', 'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ', 'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
- 'months_short' => ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ', 'ᏕᎭ', 'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
- 'weekdays' => ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ', 'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ', 'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
- 'weekdays_short' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
- 'weekdays_min' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ᏌᎾᎴ', 'ᏒᎯᏱᎢᏗᏢ'],
-
- 'second' => ':count ᏐᎢ', // less reliable
- 's' => ':count ᏐᎢ', // less reliable
- 'a_second' => ':count ᏐᎢ', // less reliable
-
- 'year' => ':count ᏑᏕᏘᏴᏓ',
- 'y' => ':count ᏑᏕᏘᏴᏓ',
- 'a_year' => ':count ᏑᏕᏘᏴᏓ',
-
- 'month' => ':count ᏏᏅᏙ',
- 'm' => ':count ᏏᏅᏙ',
- 'a_month' => ':count ᏏᏅᏙ',
-
- 'week' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
- 'w' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
- 'a_week' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
-
- 'day' => ':count ᎢᎦ',
- 'd' => ':count ᎢᎦ',
- 'a_day' => ':count ᎢᎦ',
-
- 'hour' => ':count ᏑᏟᎶᏛ',
- 'h' => ':count ᏑᏟᎶᏛ',
- 'a_hour' => ':count ᏑᏟᎶᏛ',
-
- 'minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
- 'min' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
- 'a_minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
-
- 'ago' => ':time ᏥᎨᏒ',
- 'from_now' => 'ᎾᎿ :time',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/cmn_TW.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY年MM月DD號',
- ],
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'meridiem' => ['上午', '下午'],
-
- 'year' => ':count 年',
- 'y' => ':count 年',
- 'a_year' => ':count 年',
-
- 'month' => ':count 月',
- 'm' => ':count 月',
- 'a_month' => ':count 月',
-
- 'week' => ':count 周',
- 'w' => ':count 周',
- 'a_week' => ':count 周',
-
- 'day' => ':count 白天',
- 'd' => ':count 白天',
- 'a_day' => ':count 白天',
-
- 'hour' => ':count 小时',
- 'h' => ':count 小时',
- 'a_hour' => ':count 小时',
-
- 'minute' => ':count 分钟',
- 'min' => ':count 分钟',
- 'a_minute' => ':count 分钟',
-
- 'second' => ':count 秒',
- 's' => ':count 秒',
- 'a_second' => ':count 秒',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/crh_UA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Reşat SABIQ tilde.birlik@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'Mayıs', 'İyun', 'İyul', 'Avgust', 'Sentâbr', 'Oktâbr', 'Noyabr', 'Dekabr'],
- 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
- 'weekdays' => ['Bazar', 'Bazarertesi', 'Salı', 'Çarşembe', 'Cumaaqşamı', 'Cuma', 'Cumaertesi'],
- 'weekdays_short' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'],
- 'weekdays_min' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ÜE', 'ÜS'],
-
- 'year' => ':count yıl',
- 'y' => ':count yıl',
- 'a_year' => ':count yıl',
-
- 'month' => ':count ay',
- 'm' => ':count ay',
- 'a_month' => ':count ay',
-
- 'week' => ':count afta',
- 'w' => ':count afta',
- 'a_week' => ':count afta',
-
- 'day' => ':count kün',
- 'd' => ':count kün',
- 'a_day' => ':count kün',
-
- 'hour' => ':count saat',
- 'h' => ':count saat',
- 'a_hour' => ':count saat',
-
- 'minute' => ':count daqqa',
- 'min' => ':count daqqa',
- 'a_minute' => ':count daqqa',
-
- 'second' => ':count ekinci',
- 's' => ':count ekinci',
- 'a_second' => ':count ekinci',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Jakub Tesinsky
- * - Martin Suja
- * - Nikos Timiopulos
- * - Bohuslav Blín
- * - Tsutomu Kuroda
- * - tjku
- * - Lukas Svoboda
- * - Max Melentiev
- * - Juanito Fatas
- * - Akira Matsuda
- * - Christopher Dell
- * - Václav Pávek
- * - CodeSkills
- * - Tlapi
- * - newman101
- * - Petr Kadlec
- * - tommaskraus
- * - Karel Sommer (calvera)
- */
-$za = function ($time) {
- return 'za '.strtr($time, [
- 'hodina' => 'hodinu',
- 'minuta' => 'minutu',
- 'sekunda' => 'sekundu',
- ]);
-};
-
-$pred = function ($time) {
- $time = strtr($time, [
- 'hodina' => 'hodinou',
- 'minuta' => 'minutou',
- 'sekunda' => 'sekundou',
- ]);
- $time = preg_replace('/hodiny?(?!\w)/', 'hodinami', $time);
- $time = preg_replace('/minuty?(?!\w)/', 'minutami', $time);
- $time = preg_replace('/sekundy?(?!\w)/', 'sekundami', $time);
-
- return "před $time";
-};
-
-return [
- 'year' => ':count rok|:count roky|:count let',
- 'y' => ':count rok|:count roky|:count let',
- 'a_year' => 'rok|:count roky|:count let',
- 'month' => ':count měsíc|:count měsíce|:count měsíců',
- 'm' => ':count měs.',
- 'a_month' => 'měsíc|:count měsíce|:count měsíců',
- 'week' => ':count týden|:count týdny|:count týdnů',
- 'w' => ':count týd.',
- 'a_week' => 'týden|:count týdny|:count týdnů',
- 'day' => ':count den|:count dny|:count dní',
- 'd' => ':count den|:count dny|:count dní',
- 'a_day' => 'den|:count dny|:count dní',
- 'hour' => ':count hodina|:count hodiny|:count hodin',
- 'h' => ':count hod.',
- 'a_hour' => 'hodina|:count hodiny|:count hodin',
- 'minute' => ':count minuta|:count minuty|:count minut',
- 'min' => ':count min.',
- 'a_minute' => 'minuta|:count minuty|:count minut',
- 'second' => ':count sekunda|:count sekundy|:count sekund',
- 's' => ':count sek.',
- 'a_second' => 'pár sekund|:count sekundy|:count sekund',
- 'ago' => $pred,
- 'from_now' => $za,
- 'before' => $pred,
- 'after' => $za,
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'months' => ['leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
- 'months_short' => ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp', 'zář', 'říj', 'lis', 'pro'],
- 'weekdays' => ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
- 'weekdays_short' => ['ned', 'pon', 'úte', 'stř', 'čtv', 'pát', 'sob'],
- 'weekdays_min' => ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
- 'list' => [', ', ' a '],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD. MM. YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D. MMMM YYYY HH:mm',
- ],
- 'meridiem' => ['dopoledne', 'odpoledne'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/cs.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/csb_PL.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - csb_PL locale Michal Ostrowski bug-glibc-locales@gnu.org
- */
-return [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'MMMM DD, YYYY',
- 'LLL' => 'DD MMM HH:mm',
- 'LLLL' => 'MMMM DD, YYYY HH:mm',
- ],
- 'months' => ['stëcznika', 'gromicznika', 'strëmiannika', 'łżëkwiata', 'maja', 'czerwińca', 'lëpińca', 'zélnika', 'séwnika', 'rujana', 'lëstopadnika', 'gòdnika'],
- 'months_short' => ['stë', 'gro', 'str', 'łżë', 'maj', 'cze', 'lëp', 'zél', 'séw', 'ruj', 'lës', 'gòd'],
- 'weekdays' => ['niedzela', 'pòniedzôłk', 'wtórk', 'strzoda', 'czwiôrtk', 'piątk', 'sobòta'],
- 'weekdays_short' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'],
- 'weekdays_min' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' a téż '],
- 'two_words_connector' => ' a téż ',
- 'year' => ':count rok',
- 'month' => ':count miesiąc',
- 'week' => ':count tidzéń',
- 'day' => ':count dzéń',
- 'hour' => ':count gòdzëna',
- 'minute' => ':count minuta',
- 'second' => ':count sekunda',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
- 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
- ],
-
- 'year' => ':count лѣто',
- 'y' => ':count лѣто',
- 'a_year' => ':count лѣто',
-
- 'month' => ':count мѣсѧць',
- 'm' => ':count мѣсѧць',
- 'a_month' => ':count мѣсѧць',
-
- 'week' => ':count сєдмица',
- 'w' => ':count сєдмица',
- 'a_week' => ':count сєдмица',
-
- 'day' => ':count дьнь',
- 'd' => ':count дьнь',
- 'a_day' => ':count дьнь',
-
- 'hour' => ':count година',
- 'h' => ':count година',
- 'a_hour' => ':count година',
-
- 'minute' => ':count малъ', // less reliable
- 'min' => ':count малъ', // less reliable
- 'a_minute' => ':count малъ', // less reliable
-
- 'second' => ':count въторъ',
- 's' => ':count въторъ',
- 'a_second' => ':count въторъ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'cv');
-
-/*
- * Authors:
- * - Josh Soref
- * - François B
- * - JD Isaacks
- */
-return [
- 'year' => ':count ҫул',
- 'a_year' => 'пӗр ҫул|:count ҫул',
- 'month' => ':count уйӑх',
- 'a_month' => 'пӗр уйӑх|:count уйӑх',
- 'week' => ':count эрне',
- 'a_week' => 'пӗр эрне|:count эрне',
- 'day' => ':count кун',
- 'a_day' => 'пӗр кун|:count кун',
- 'hour' => ':count сехет',
- 'a_hour' => 'пӗр сехет|:count сехет',
- 'minute' => ':count минут',
- 'a_minute' => 'пӗр минут|:count минут',
- 'second' => ':count ҫеккунт',
- 'a_second' => 'пӗр-ик ҫеккунт|:count ҫеккунт',
- 'ago' => ':time каялла',
- 'from_now' => function ($time) {
- return $time.(preg_match('/сехет$/', $time) ? 'рен' : (preg_match('/ҫул/', $time) ? 'тан' : 'ран'));
- },
- 'diff_yesterday' => 'Ӗнер',
- 'diff_tomorrow' => 'Ыран',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD-MM-YYYY',
- 'LL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
- 'LLL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
- 'LLLL' => 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Паян] LT [сехетре]',
- 'nextDay' => '[Ыран] LT [сехетре]',
- 'nextWeek' => '[Ҫитес] dddd LT [сехетре]',
- 'lastDay' => '[Ӗнер] LT [сехетре]',
- 'lastWeek' => '[Иртнӗ] dddd LT [сехетре]',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number-мӗш',
- 'months' => ['кӑрлач', 'нарӑс', 'пуш', 'ака', 'май', 'ҫӗртме', 'утӑ', 'ҫурла', 'авӑн', 'юпа', 'чӳк', 'раштав'],
- 'months_short' => ['кӑр', 'нар', 'пуш', 'ака', 'май', 'ҫӗр', 'утӑ', 'ҫур', 'авн', 'юпа', 'чӳк', 'раш'],
- 'weekdays' => ['вырсарникун', 'тунтикун', 'ытларикун', 'юнкун', 'кӗҫнерникун', 'эрнекун', 'шӑматкун'],
- 'weekdays_short' => ['выр', 'тун', 'ытл', 'юн', 'кӗҫ', 'эрн', 'шӑм'],
- 'weekdays_min' => ['вр', 'тн', 'ыт', 'юн', 'кҫ', 'эр', 'шм'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' тата '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/cv.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - JD Isaacks
- * - Daniel Monaghan
- */
-return [
- 'year' => '{1}blwyddyn|]1,Inf[:count flynedd',
- 'y' => ':countbl',
- 'month' => '{1}mis|]1,Inf[:count mis',
- 'm' => ':countmi',
- 'week' => ':count wythnos',
- 'w' => ':countw',
- 'day' => '{1}diwrnod|]1,Inf[:count diwrnod',
- 'd' => ':countd',
- 'hour' => '{1}awr|]1,Inf[:count awr',
- 'h' => ':counth',
- 'minute' => '{1}munud|]1,Inf[:count munud',
- 'min' => ':countm',
- 'second' => '{1}ychydig eiliadau|]1,Inf[:count eiliad',
- 's' => ':counts',
- 'ago' => ':time yn ôl',
- 'from_now' => 'mewn :time',
- 'after' => ':time ar ôl',
- 'before' => ':time o\'r blaen',
- 'diff_yesterday' => 'Ddoe',
- 'diff_tomorrow' => 'Yfory',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Heddiw am] LT',
- 'nextDay' => '[Yfory am] LT',
- 'nextWeek' => 'dddd [am] LT',
- 'lastDay' => '[Ddoe am] LT',
- 'lastWeek' => 'dddd [diwethaf am] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- return $number.($number > 20
- ? (in_array($number, [40, 50, 60, 80, 100]) ? 'fed' : 'ain')
- : ([
- '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
- 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed', // 11eg to 20fed
- ])[$number] ?? ''
- );
- },
- 'months' => ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin', 'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
- 'months_short' => ['Ion', 'Chwe', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor', 'Aws', 'Med', 'Hyd', 'Tach', 'Rhag'],
- 'weekdays' => ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],
- 'weekdays_short' => ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],
- 'weekdays_min' => ['Su', 'Ll', 'Ma', 'Me', 'Ia', 'Gw', 'Sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' a '],
- 'meridiem' => ['yb', 'yh'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/cy.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Rune Mønnike
- * - François B
- * - codenhagen
- * - JD Isaacks
- * - Jens Herlevsen
- * - Ulrik McArdle (mcardle)
- * - Frederik Sauer (FrittenKeeZ)
- */
-return [
- 'year' => ':count år|:count år',
- 'a_year' => 'et år|:count år',
- 'y' => ':count år|:count år',
- 'month' => ':count måned|:count måneder',
- 'a_month' => 'en måned|:count måneder',
- 'm' => ':count mdr.',
- 'week' => ':count uge|:count uger',
- 'a_week' => 'en uge|:count uger',
- 'w' => ':count u.',
- 'day' => ':count dag|:count dage',
- 'a_day' => ':count dag|:count dage',
- 'd' => ':count d.',
- 'hour' => ':count time|:count timer',
- 'a_hour' => 'en time|:count timer',
- 'h' => ':count t.',
- 'minute' => ':count minut|:count minutter',
- 'a_minute' => 'et minut|:count minutter',
- 'min' => ':count min.',
- 'second' => ':count sekund|:count sekunder',
- 'a_second' => 'få sekunder|:count sekunder',
- 's' => ':count s.',
- 'ago' => ':time siden',
- 'from_now' => 'om :time',
- 'after' => ':time efter',
- 'before' => ':time før',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY HH:mm',
- 'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[i dag kl.] LT',
- 'nextDay' => '[i morgen kl.] LT',
- 'nextWeek' => 'på dddd [kl.] LT',
- 'lastDay' => '[i går kl.] LT',
- 'lastWeek' => '[i] dddd[s kl.] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'december'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
- 'weekdays_short' => ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
- 'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' og '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/da.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/da.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D. MMM YYYY',
- 'LLL' => 'D. MMMM YYYY HH.mm',
- 'LLLL' => 'dddd [den] D. MMMM YYYY HH.mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Luma lwa K', 'luma lwa p'],
- 'weekdays' => ['Ituku ja jumwa', 'Kuramuka jimweri', 'Kuramuka kawi', 'Kuramuka kadadu', 'Kuramuka kana', 'Kuramuka kasanu', 'Kifula nguwo'],
- 'weekdays_short' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
- 'weekdays_min' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
- 'months' => ['Mori ghwa imbiri', 'Mori ghwa kawi', 'Mori ghwa kadadu', 'Mori ghwa kana', 'Mori ghwa kasanu', 'Mori ghwa karandadu', 'Mori ghwa mfungade', 'Mori ghwa wunyanya', 'Mori ghwa ikenda', 'Mori ghwa ikumi', 'Mori ghwa ikumi na imweri', 'Mori ghwa ikumi na iwi'],
- 'months_short' => ['Imb', 'Kaw', 'Kad', 'Kan', 'Kas', 'Kar', 'Mfu', 'Wun', 'Ike', 'Iku', 'Imw', 'Iwi'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Michael Hohl
- * - sheriffmarley
- * - dennisoderwald
- * - Timo
- * - Karag2006
- */
-return [
- 'year' => ':count Jahr|:count Jahre',
- 'a_year' => 'ein Jahr|:count Jahre',
- 'y' => ':count J.',
- 'month' => ':count Monat|:count Monate',
- 'a_month' => 'ein Monat|:count Monate',
- 'm' => ':count Mon.',
- 'week' => ':count Woche|:count Wochen',
- 'a_week' => 'eine Woche|:count Wochen',
- 'w' => ':count Wo.',
- 'day' => ':count Tag|:count Tage',
- 'a_day' => 'ein Tag|:count Tage',
- 'd' => ':count Tg.',
- 'hour' => ':count Stunde|:count Stunden',
- 'a_hour' => 'eine Stunde|:count Stunden',
- 'h' => ':count Std.',
- 'minute' => ':count Minute|:count Minuten',
- 'a_minute' => 'eine Minute|:count Minuten',
- 'min' => ':count Min.',
- 'second' => ':count Sekunde|:count Sekunden',
- 'a_second' => 'ein paar Sekunden|:count Sekunden',
- 's' => ':count Sek.',
- 'ago' => 'vor :time',
- 'from_now' => 'in :time',
- 'after' => ':time später',
- 'before' => ':time zuvor',
-
- 'year_from_now' => ':count Jahr|:count Jahren',
- 'month_from_now' => ':count Monat|:count Monaten',
- 'week_from_now' => ':count Woche|:count Wochen',
- 'day_from_now' => ':count Tag|:count Tagen',
- 'year_ago' => ':count Jahr|:count Jahren',
- 'month_ago' => ':count Monat|:count Monaten',
- 'week_ago' => ':count Woche|:count Wochen',
- 'day_ago' => ':count Tag|:count Tagen',
-
- 'diff_now' => 'Gerade eben',
- 'diff_yesterday' => 'Gestern',
- 'diff_tomorrow' => 'Heute',
- 'diff_before_yesterday' => 'Vorgestern',
- 'diff_after_tomorrow' => 'Übermorgen',
-
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY HH:mm',
- ],
-
- 'calendar' => [
- 'sameDay' => '[heute um] LT [Uhr]',
- 'nextDay' => '[morgen um] LT [Uhr]',
- 'nextWeek' => 'dddd [um] LT [Uhr]',
- 'lastDay' => '[gestern um] LT [Uhr]',
- 'lastWeek' => '[letzten] dddd [um] LT [Uhr]',
- 'sameElse' => 'L',
- ],
-
- 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
- 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
- 'weekdays' => ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
- 'weekdays_short' => ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
- 'weekdays_min' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
- 'ordinal' => ':number.',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' und '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - sheriffmarley
- * - Timo
- * - Michael Hohl
- * - Namoshek
- */
-return require __DIR__.'/de.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/de.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - sheriffmarley
- * - Timo
- * - Michael Hohl
- */
-return array_replace_recursive(require __DIR__.'/de.php', [
- 'weekdays_short' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return require __DIR__.'/de.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Matthias Dieter Wallno:fer libc-locales@sourceware.org
- */
-return require __DIR__.'/de.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/de.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/de.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Subbaahi', 'Zaarikay b'],
- 'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamisi', 'Alzuma', 'Asibti'],
- 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
- 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
- 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
- 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count hari', // less reliable
- 'y' => ':count hari', // less reliable
- 'a_year' => ':count hari', // less reliable
-
- 'week' => ':count alzuma', // less reliable
- 'w' => ':count alzuma', // less reliable
- 'a_week' => ':count alzuma', // less reliable
-
- 'second' => ':count atinni', // less reliable
- 's' => ':count atinni', // less reliable
- 'a_second' => ':count atinni', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/doi_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat Pune libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'],
- 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'],
- 'weekdays' => ['ऐतबार', 'सोमबार', 'मंगलबर', 'बुधबार', 'बीरबार', 'शुक्करबार', 'श्नीचरबार'],
- 'weekdays_short' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'],
- 'weekdays_min' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['सञं', 'सबेर'],
-
- 'second' => ':count सङार', // less reliable
- 's' => ':count सङार', // less reliable
- 'a_second' => ':count सङार', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/dsb_DE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Information from Michael Wolf bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'DD. MMMM YYYY',
- 'LLL' => 'DD. MMMM, HH:mm [góź.]',
- 'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [góź.]',
- ],
- 'months' => ['januara', 'februara', 'měrca', 'apryla', 'maja', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
- 'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Maj', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'],
- 'weekdays' => ['Njeźela', 'Pónjeźele', 'Wałtora', 'Srjoda', 'Stwórtk', 'Pětk', 'Sobota'],
- 'weekdays_short' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'],
- 'weekdays_min' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count lěto',
- 'y' => ':count lěto',
- 'a_year' => ':count lěto',
-
- 'month' => ':count mjasec',
- 'm' => ':count mjasec',
- 'a_month' => ':count mjasec',
-
- 'week' => ':count tyźeń',
- 'w' => ':count tyźeń',
- 'a_week' => ':count tyźeń',
-
- 'day' => ':count źeń',
- 'd' => ':count źeń',
- 'a_day' => ':count źeń',
-
- 'hour' => ':count góźina',
- 'h' => ':count góźina',
- 'a_hour' => ':count góźina',
-
- 'minute' => ':count minuta',
- 'min' => ':count minuta',
- 'a_minute' => ':count minuta',
-
- 'second' => ':count drugi',
- 's' => ':count drugi',
- 'a_second' => ':count drugi',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['idiɓa', 'ebyámu'],
- 'weekdays' => ['éti', 'mɔ́sú', 'kwasú', 'mukɔ́sú', 'ŋgisú', 'ɗónɛsú', 'esaɓasú'],
- 'weekdays_short' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
- 'weekdays_min' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
- 'months' => ['dimɔ́di', 'ŋgɔndɛ', 'sɔŋɛ', 'diɓáɓá', 'emiasele', 'esɔpɛsɔpɛ', 'madiɓɛ́díɓɛ́', 'diŋgindi', 'nyɛtɛki', 'mayésɛ́', 'tiníní', 'eláŋgɛ́'],
- 'months_short' => ['di', 'ŋgɔn', 'sɔŋ', 'diɓ', 'emi', 'esɔ', 'mad', 'diŋ', 'nyɛt', 'may', 'tin', 'elá'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count ma mbu', // less reliable
- 'y' => ':count ma mbu', // less reliable
- 'a_year' => ':count ma mbu', // less reliable
-
- 'month' => ':count myo̱di', // less reliable
- 'm' => ':count myo̱di', // less reliable
- 'a_month' => ':count myo̱di', // less reliable
-
- 'week' => ':count woki', // less reliable
- 'w' => ':count woki', // less reliable
- 'a_week' => ':count woki', // less reliable
-
- 'day' => ':count buńa', // less reliable
- 'd' => ':count buńa', // less reliable
- 'a_day' => ':count buńa', // less reliable
-
- 'hour' => ':count ma awa', // less reliable
- 'h' => ':count ma awa', // less reliable
- 'a_hour' => ':count ma awa', // less reliable
-
- 'minute' => ':count minuti', // less reliable
- 'min' => ':count minuti', // less reliable
- 'a_minute' => ':count minuti', // less reliable
-
- 'second' => ':count maba', // less reliable
- 's' => ':count maba', // less reliable
- 'a_second' => ':count maba', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'dv');
-
-$months = [
- 'ޖެނުއަރީ',
- 'ފެބްރުއަރީ',
- 'މާރިޗު',
- 'އޭޕްރީލު',
- 'މޭ',
- 'ޖޫން',
- 'ޖުލައި',
- 'އޯގަސްޓު',
- 'ސެޕްޓެމްބަރު',
- 'އޮކްޓޯބަރު',
- 'ނޮވެމްބަރު',
- 'ޑިސެމްބަރު',
-];
-
-$weekdays = [
- 'އާދިއްތަ',
- 'ހޯމަ',
- 'އަންގާރަ',
- 'ބުދަ',
- 'ބުރާސްފަތި',
- 'ހުކުރު',
- 'ހޮނިހިރު',
-];
-
-/*
- * Authors:
- * - Josh Soref
- * - Jawish Hameed
- */
-return [
- 'year' => ':count '.'އަހަރު',
- 'a_year' => 'އަހަރެއް'.'|:count '.'އަހަރު',
- 'month' => ':count '.'މަސް',
- 'a_month' => 'މަހެއް'.'|:count '.'މަސް',
- 'week' => ':count '.'ހަފްތާ',
- 'a_week' => 'ސިކުންތުކޮޅެއް'.'|:count '.'ހަފްތާ',
- 'day' => ':count '.'ދުވަސް',
- 'a_day' => 'ދުވަހެއް'.'|:count '.'ދުވަސް',
- 'hour' => ':count '.'ގަޑިއިރު',
- 'a_hour' => 'ގަޑިއިރެއް'.'|:count '.'ގަޑިއިރު',
- 'minute' => ':count '.'މިނިޓު',
- 'a_minute' => 'މިނިޓެއް'.'|:count '.'މިނިޓު',
- 'second' => ':count '.'ސިކުންތު',
- 'a_second' => 'ސިކުންތުކޮޅެއް'.'|:count '.'ސިކުންތު',
- 'ago' => 'ކުރިން :time',
- 'from_now' => 'ތެރޭގައި :time',
- 'after' => ':time ފަހުން',
- 'before' => ':time ކުރި',
- 'diff_yesterday' => 'އިއްޔެ',
- 'diff_tomorrow' => 'މާދަމާ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[މިއަދު] LT',
- 'nextDay' => '[މާދަމާ] LT',
- 'nextWeek' => 'dddd LT',
- 'lastDay' => '[އިއްޔެ] LT',
- 'lastWeek' => '[ފާއިތުވި] dddd LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['މކ', 'މފ'],
- 'months' => $months,
- 'months_short' => $months,
- 'weekdays' => $weekdays,
- 'weekdays_short' => $weekdays,
- 'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'],
- 'list' => [', ', ' އަދި '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Ahmed Ali <ajaaibu@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Ahmed Ali
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'dv');
-
-$months = [
- 'ޖެނުއަރީ',
- 'ފެބްރުއަރީ',
- 'މާރިޗު',
- 'އޭޕްރީލު',
- 'މޭ',
- 'ޖޫން',
- 'ޖުލައި',
- 'އޯގަސްޓު',
- 'ސެޕްޓެމްބަރު',
- 'އޮކްޓޯބަރު',
- 'ނޮވެމްބަރު',
- 'ޑިސެމްބަރު',
-];
-
-$weekdays = [
- 'އާދިއްތަ',
- 'ހޯމަ',
- 'އަންގާރަ',
- 'ބުދަ',
- 'ބުރާސްފަތި',
- 'ހުކުރު',
- 'ހޮނިހިރު',
-];
-
-return [
- 'year' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
- 'y' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
- 'month' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
- 'm' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
- 'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
- 'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
- 'day' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
- 'd' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
- 'hour' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
- 'h' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
- 'minute' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
- 'min' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
- 'second' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
- 's' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
- 'ago' => ':time ކުރިން',
- 'from_now' => ':time ފަހުން',
- 'after' => ':time ފަހުން',
- 'before' => ':time ކުރި',
- 'diff_yesterday' => 'އިއްޔެ',
- 'diff_tomorrow' => 'މާދަމާ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[މިއަދު] LT',
- 'nextDay' => '[މާދަމާ] LT',
- 'nextWeek' => 'dddd LT',
- 'lastDay' => '[އިއްޔެ] LT',
- 'lastWeek' => '[ފާއިތުވި] dddd LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['މކ', 'މފ'],
- 'months' => $months,
- 'months_short' => $months,
- 'weekdays' => $weekdays,
- 'weekdays_short' => $weekdays,
- 'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'],
- 'list' => [', ', ' އަދި '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Dimas', 'Teneŋ', 'Talata', 'Alarbay', 'Aramisay', 'Arjuma', 'Sibiti'],
- 'weekdays_short' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
- 'weekdays_min' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
- 'months' => ['Sanvie', 'Fébirie', 'Mars', 'Aburil', 'Mee', 'Sueŋ', 'Súuyee', 'Ut', 'Settembar', 'Oktobar', 'Novembar', 'Disambar'],
- 'months_short' => ['Sa', 'Fe', 'Ma', 'Ab', 'Me', 'Su', 'Sú', 'Ut', 'Se', 'Ok', 'No', 'De'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/dz_BT.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Sherubtse College bug-glibc@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'པསྱི་ལོYYཟལMMཚེསDD',
- ],
- 'months' => ['ཟླ་བ་དང་པ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་ཕ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུནཔ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
- 'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
- 'weekdays' => ['གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་ཕ་', 'གཟའ་པུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་ཕ་', 'གཟའ་ཉི་མ་'],
- 'weekdays_short' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
- 'weekdays_min' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ངས་ཆ', 'ཕྱི་ཆ'],
-
- 'year' => ':count ཆརཔ', // less reliable
- 'y' => ':count ཆརཔ', // less reliable
- 'a_year' => ':count ཆརཔ', // less reliable
-
- 'month' => ':count ཟླ་བ', // less reliable
- 'm' => ':count ཟླ་བ', // less reliable
- 'a_month' => ':count ཟླ་བ', // less reliable
-
- 'day' => ':count ཉི', // less reliable
- 'd' => ':count ཉི', // less reliable
- 'a_day' => ':count ཉི', // less reliable
-
- 'second' => ':count ཆ', // less reliable
- 's' => ':count ཆ', // less reliable
- 'a_second' => ':count ཆ', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['KI', 'UT'],
- 'weekdays' => ['Kiumia', 'Njumatatu', 'Njumaine', 'Njumatano', 'Aramithi', 'Njumaa', 'NJumamothii'],
- 'weekdays_short' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
- 'weekdays_min' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
- 'months' => ['Mweri wa mbere', 'Mweri wa kaĩri', 'Mweri wa kathatũ', 'Mweri wa kana', 'Mweri wa gatano', 'Mweri wa gatantatũ', 'Mweri wa mũgwanja', 'Mweri wa kanana', 'Mweri wa kenda', 'Mweri wa ikũmi', 'Mweri wa ikũmi na ũmwe', 'Mweri wa ikũmi na Kaĩrĩ'],
- 'months_short' => ['Mbe', 'Kai', 'Kat', 'Kan', 'Gat', 'Gan', 'Mug', 'Knn', 'Ken', 'Iku', 'Imw', 'Igi'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['ŋ', 'ɣ'],
- 'weekdays' => ['kɔsiɖa', 'dzoɖa', 'blaɖa', 'kuɖa', 'yawoɖa', 'fiɖa', 'memleɖa'],
- 'weekdays_short' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
- 'weekdays_min' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
- 'months' => ['dzove', 'dzodze', 'tedoxe', 'afɔfĩe', 'dama', 'masa', 'siamlɔm', 'deasiamime', 'anyɔnyɔ', 'kele', 'adeɛmekpɔxe', 'dzome'],
- 'months_short' => ['dzv', 'dzd', 'ted', 'afɔ', 'dam', 'mas', 'sia', 'dea', 'any', 'kel', 'ade', 'dzm'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'a [ga] h:mm',
- 'LTS' => 'a [ga] h:mm:ss',
- 'L' => 'M/D/YYYY',
- 'LL' => 'MMM D [lia], YYYY',
- 'LLL' => 'a [ga] h:mm MMMM D [lia] YYYY',
- 'LLLL' => 'a [ga] h:mm dddd, MMMM D [lia] YYYY',
- ],
-
- 'year' => 'ƒe :count',
- 'y' => 'ƒe :count',
- 'a_year' => 'ƒe :count',
-
- 'month' => 'ɣleti :count',
- 'm' => 'ɣleti :count',
- 'a_month' => 'ɣleti :count',
-
- 'week' => 'kwasiɖa :count',
- 'w' => 'kwasiɖa :count',
- 'a_week' => 'kwasiɖa :count',
-
- 'day' => 'ŋkeke :count',
- 'd' => 'ŋkeke :count',
- 'a_day' => 'ŋkeke :count',
-
- 'hour' => 'gaƒoƒo :count',
- 'h' => 'gaƒoƒo :count',
- 'a_hour' => 'gaƒoƒo :count',
-
- 'minute' => 'miniti :count', // less reliable
- 'min' => 'miniti :count', // less reliable
- 'a_minute' => 'miniti :count', // less reliable
-
- 'second' => 'sɛkɛnd :count', // less reliable
- 's' => 'sɛkɛnd :count', // less reliable
- 'a_second' => 'sɛkɛnd :count', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ee.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'LLL' => 'HH:mm MMMM D [lia] YYYY',
- 'LLLL' => 'HH:mm dddd, MMMM D [lia] YYYY',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Alessandro Di Felice
- * - François B
- * - Tim Fish
- * - Gabriel Monteagudo
- * - JD Isaacks
- * - yiannisdesp
- * - Ilias Kasmeridis (iliaskasm)
- */
-return [
- 'year' => ':count χρόνος|:count χρόνια',
- 'a_year' => 'ένας χρόνος|:count χρόνια',
- 'y' => ':count χρ.',
- 'month' => ':count μήνας|:count μήνες',
- 'a_month' => 'ένας μήνας|:count μήνες',
- 'm' => ':count μήν.',
- 'week' => ':count εβδομάδα|:count εβδομάδες',
- 'a_week' => 'μια εβδομάδα|:count εβδομάδες',
- 'w' => ':count εβδ.',
- 'day' => ':count μέρα|:count μέρες',
- 'a_day' => 'μία μέρα|:count μέρες',
- 'd' => ':count μέρ.',
- 'hour' => ':count ώρα|:count ώρες',
- 'a_hour' => 'μία ώρα|:count ώρες',
- 'h' => ':count ώρα|:count ώρες',
- 'minute' => ':count λεπτό|:count λεπτά',
- 'a_minute' => 'ένα λεπτό|:count λεπτά',
- 'min' => ':count λεπ.',
- 'second' => ':count δευτερόλεπτο|:count δευτερόλεπτα',
- 'a_second' => 'λίγα δευτερόλεπτα|:count δευτερόλεπτα',
- 's' => ':count δευ.',
- 'ago' => ':time πριν',
- 'from_now' => 'σε :time',
- 'after' => ':time μετά',
- 'before' => ':time πριν',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm A',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
- ],
- 'calendar' => [
- 'sameDay' => '[Σήμερα {}] LT',
- 'nextDay' => '[Αύριο {}] LT',
- 'nextWeek' => 'dddd [{}] LT',
- 'lastDay' => '[Χθες {}] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- switch ($current->dayOfWeek) {
- case 6:
- return '[το προηγούμενο] dddd [{}] LT';
- default:
- return '[την προηγούμενη] dddd [{}] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberη',
- 'meridiem' => ['ΠΜ', 'ΜΜ', 'πμ', 'μμ'],
- 'months' => ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου', 'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου', 'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου', 'Νοεμβρίου', 'Δεκεμβρίου'],
- 'months_standalone' => ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],
- 'months_regexp' => '/D[oD]?[\s,]+MMMM/',
- 'months_short' => ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαϊ', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],
- 'weekdays' => ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
- 'weekdays_short' => ['Κυρ', 'Δευ', 'Τρι', 'Τετ', 'Πεμ', 'Παρ', 'Σαβ'],
- 'weekdays_min' => ['Κυ', 'Δε', 'Τρ', 'Τε', 'Πε', 'Πα', 'Σα'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' και '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Greek Debian Translation Team bug-glibc@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/el.php', [
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/el.php', [
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Milos Sakovic
- * - Paul
- */
-return [
- 'year' => '{1}:count year|{0}:count years|]1,Inf[:count years',
- 'a_year' => '{1}a year|{0}:count years|]1,Inf[:count years',
- 'y' => '{1}:countyr|{0}:countyrs|]1,Inf[:countyrs',
- 'month' => '{1}:count month|{0}:count months|]1,Inf[:count months',
- 'a_month' => '{1}a month|{0}:count months|]1,Inf[:count months',
- 'm' => '{1}:countmo|{0}:countmos|]1,Inf[:countmos',
- 'week' => '{1}:count week|{0}:count weeks|]1,Inf[:count weeks',
- 'a_week' => '{1}a week|{0}:count weeks|]1,Inf[:count weeks',
- 'w' => ':countw',
- 'day' => '{1}:count day|{0}:count days|]1,Inf[:count days',
- 'a_day' => '{1}a day|{0}:count days|]1,Inf[:count days',
- 'd' => ':countd',
- 'hour' => '{1}:count hour|{0}:count hours|]1,Inf[:count hours',
- 'a_hour' => '{1}an hour|{0}:count hours|]1,Inf[:count hours',
- 'h' => ':counth',
- 'minute' => '{1}:count minute|{0}:count minutes|]1,Inf[:count minutes',
- 'a_minute' => '{1}a minute|{0}:count minutes|]1,Inf[:count minutes',
- 'min' => ':countm',
- 'second' => '{1}:count second|{0}:count seconds|]1,Inf[:count seconds',
- 'a_second' => '{1}a few seconds|{0}:count seconds|]1,Inf[:count seconds',
- 's' => ':counts',
- 'ago' => ':time ago',
- 'from_now' => ':time from now',
- 'after' => ':time after',
- 'before' => ':time before',
- 'diff_now' => 'just now',
- 'diff_yesterday' => 'yesterday',
- 'diff_tomorrow' => 'tomorrow',
- 'diff_before_yesterday' => 'before yesterday',
- 'diff_after_tomorrow' => 'after tomorrow',
- 'period_recurrences' => '{1}once|{0}:count times|]1,Inf[:count times',
- 'period_interval' => 'every :interval',
- 'period_start_date' => 'from :date',
- 'period_end_date' => 'to :date',
- 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- 'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
- 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- 'weekdays_min' => ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
- 'ordinal' => function ($number) {
- $lastDigit = $number % 10;
-
- return $number.(
- (~~($number % 100 / 10) === 1) ? 'th' : (
- ($lastDigit === 1) ? 'st' : (
- ($lastDigit === 2) ? 'nd' : (
- ($lastDigit === 3) ? 'rd' : 'th'
- )
- )
- )
- );
- },
- 'list' => [', ', ' and '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kunal Marwaha
- * - François B
- * - Mayank Badola
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm A',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Zhan Tong Zhang
- * - Mayank Badola
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'MMMM D, YYYY',
- 'LLL' => 'MMMM D, YYYY h:mm A',
- 'LLLL' => 'dddd, MMMM D, YYYY h:mm A',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - NehaGautam
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD-MM-YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Danish Standards Association bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Mayank Badola
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Martin McWhorter
- * - François B
- * - Chris Cartlidge
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD-MM-YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Yoav Amit
- * - François B
- * - Mayank Badola
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YY',
- 'LL' => 'MMMM DD, YYYY',
- 'LLL' => 'DD MMM HH:mm',
- 'LLLL' => 'MMMM DD, YYYY HH:mm',
- ],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'dddd, YYYY MMMM DD HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Mayank Badola
- * - Luke McGregor
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm A',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'from_now' => 'in :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YY',
- 'LL' => 'MMMM DD, YYYY',
- 'LLL' => 'DD MMM HH:mm',
- 'LLLL' => 'MMMM DD, YYYY HH:mm',
- ],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - ANLoc Martin Benjamin locales@africanlocalization.net
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/en.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - Mia Nordentoft
- * - JD Isaacks
- */
-return [
- 'year' => ':count jaro|:count jaroj',
- 'a_year' => 'jaro|:count jaroj',
- 'y' => ':count j.',
- 'month' => ':count monato|:count monatoj',
- 'a_month' => 'monato|:count monatoj',
- 'm' => ':count mo.',
- 'week' => ':count semajno|:count semajnoj',
- 'a_week' => 'semajno|:count semajnoj',
- 'w' => ':count sem.',
- 'day' => ':count tago|:count tagoj',
- 'a_day' => 'tago|:count tagoj',
- 'd' => ':count t.',
- 'hour' => ':count horo|:count horoj',
- 'a_hour' => 'horo|:count horoj',
- 'h' => ':count h.',
- 'minute' => ':count minuto|:count minutoj',
- 'a_minute' => 'minuto|:count minutoj',
- 'min' => ':count min.',
- 'second' => ':count sekundo|:count sekundoj',
- 'a_second' => 'sekundoj|:count sekundoj',
- 's' => ':count sek.',
- 'ago' => 'antaŭ :time',
- 'from_now' => 'post :time',
- 'after' => ':time poste',
- 'before' => ':time antaŭe',
- 'diff_yesterday' => 'Hieraŭ',
- 'diff_tomorrow' => 'Morgaŭ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'D[-a de] MMMM, YYYY',
- 'LLL' => 'D[-a de] MMMM, YYYY HH:mm',
- 'LLLL' => 'dddd, [la] D[-a de] MMMM, YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Hodiaŭ je] LT',
- 'nextDay' => '[Morgaŭ je] LT',
- 'nextWeek' => 'dddd [je] LT',
- 'lastDay' => '[Hieraŭ je] LT',
- 'lastWeek' => '[pasinta] dddd [je] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numbera',
- 'meridiem' => ['a.t.m.', 'p.t.m.'],
- 'months' => ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio', 'julio', 'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aŭg', 'sep', 'okt', 'nov', 'dec'],
- 'weekdays' => ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo', 'sabato'],
- 'weekdays_short' => ['dim', 'lun', 'mard', 'merk', 'ĵaŭ', 'ven', 'sab'],
- 'weekdays_min' => ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' kaj '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kunal Marwaha
- * - kostas
- * - François B
- * - Tim Fish
- * - Claire Coloma
- * - Steven Heinrich
- * - JD Isaacks
- * - Raphael Amorim
- * - Jorge Y. Castillo
- * - Víctor Díaz
- * - Diego
- * - Sebastian Thierer
- * - quinterocesar
- * - Daniel Commesse Liévanos (danielcommesse)
- */
-return [
- 'year' => ':count año|:count años',
- 'a_year' => 'un año|:count años',
- 'y' => ':count año|:count años',
- 'month' => ':count mes|:count meses',
- 'a_month' => 'un mes|:count meses',
- 'm' => ':count mes|:count meses',
- 'week' => ':count semana|:count semanas',
- 'a_week' => 'una semana|:count semanas',
- 'w' => ':countsem',
- 'day' => ':count día|:count días',
- 'a_day' => 'un día|:count días',
- 'd' => ':countd',
- 'hour' => ':count hora|:count horas',
- 'a_hour' => 'una hora|:count horas',
- 'h' => ':counth',
- 'minute' => ':count minuto|:count minutos',
- 'a_minute' => 'un minuto|:count minutos',
- 'min' => ':countm',
- 'second' => ':count segundo|:count segundos',
- 'a_second' => 'unos segundos|:count segundos',
- 's' => ':counts',
- 'ago' => 'hace :time',
- 'from_now' => 'en :time',
- 'after' => ':time después',
- 'before' => ':time antes',
- 'diff_now' => 'ahora mismo',
- 'diff_yesterday' => 'ayer',
- 'diff_tomorrow' => 'mañana',
- 'diff_before_yesterday' => 'antier',
- 'diff_after_tomorrow' => 'pasado mañana',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D [de] MMMM [de] YYYY',
- 'LLL' => 'D [de] MMMM [de] YYYY H:mm',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => function (\Carbon\CarbonInterface $current) {
- return '[hoy a la'.($current->hour !== 1 ? 's' : '').'] LT';
- },
- 'nextDay' => function (\Carbon\CarbonInterface $current) {
- return '[mañana a la'.($current->hour !== 1 ? 's' : '').'] LT';
- },
- 'nextWeek' => function (\Carbon\CarbonInterface $current) {
- return 'dddd [a la'.($current->hour !== 1 ? 's' : '').'] LT';
- },
- 'lastDay' => function (\Carbon\CarbonInterface $current) {
- return '[ayer a la'.($current->hour !== 1 ? 's' : '').'] LT';
- },
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- return '[el] dddd [pasado a la'.($current->hour !== 1 ? 's' : '').'] LT';
- },
- 'sameElse' => 'L',
- ],
- 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
- 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
- 'mmm_suffix' => '.',
- 'ordinal' => ':numberº',
- 'weekdays' => ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
- 'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
- 'weekdays_min' => ['do', 'lu', 'ma', 'mi', 'ju', 'vi', 'sá'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' y '],
- 'meridiem' => ['a. m.', 'p. m.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - kostas
- * - François B
- * - Tim Fish
- * - Chiel Robben
- * - Claire Coloma
- * - Steven Heinrich
- * - JD Isaacks
- * - Raphael Amorim
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'diff_before_yesterday' => 'anteayer',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'LLL' => 'D [de] MMMM [de] YYYY h:mm A',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm A',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return require __DIR__.'/es.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/M/yy',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D [de] MMMM [de] YYYY h:mm a',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
- 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kunal Marwaha
- * - Josh Soref
- * - Jørn Ølmheim
- * - Craig Patik
- * - bustta
- * - François B
- * - Tim Fish
- * - Claire Coloma
- * - Steven Heinrich
- * - JD Isaacks
- * - Raphael Amorim
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'diff_before_yesterday' => 'anteayer',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'MM/DD/YYYY',
- 'LL' => 'MMMM [de] D [de] YYYY',
- 'LLL' => 'MMMM [de] D [de] YYYY h:mm A',
- 'LLLL' => 'dddd, MMMM [de] D [de] YYYY h:mm A',
- ],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
- 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'set', 'oct', 'nov', 'dic'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/es.php', [
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Andres Ivanov
- * - Tsutomu Kuroda
- * - tjku
- * - Max Melentiev
- * - Juanito Fatas
- * - RM87
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Esko Lehtme
- * - Mart Karu
- * - Nicolás Hock Isaza
- * - Kevin Valdek
- * - Zahhar Kirillov
- * - João Magalhães
- * - Ingmar
- */
-return [
- 'year' => ':count aasta|:count aastat',
- 'y' => ':count aasta|:count aastat',
- 'month' => ':count kuu|:count kuud',
- 'm' => ':count kuu|:count kuud',
- 'week' => ':count nädal|:count nädalat',
- 'w' => ':count nädal|:count nädalat',
- 'day' => ':count päev|:count päeva',
- 'd' => ':count päev|:count päeva',
- 'hour' => ':count tund|:count tundi',
- 'h' => ':count tund|:count tundi',
- 'minute' => ':count minut|:count minutit',
- 'min' => ':count minut|:count minutit',
- 'second' => ':count sekund|:count sekundit',
- 's' => ':count sekund|:count sekundit',
- 'ago' => ':time tagasi',
- 'from_now' => ':time pärast',
- 'after' => ':time pärast',
- 'before' => ':time enne',
- 'year_from_now' => ':count aasta',
- 'month_from_now' => ':count kuu',
- 'week_from_now' => ':count nädala',
- 'day_from_now' => ':count päeva',
- 'hour_from_now' => ':count tunni',
- 'minute_from_now' => ':count minuti',
- 'second_from_now' => ':count sekundi',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'diff_now' => 'nüüd',
- 'diff_yesterday' => 'eile',
- 'diff_tomorrow' => 'homme',
- 'diff_before_yesterday' => 'üleeile',
- 'diff_after_tomorrow' => 'ülehomme',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'DD. MMMM YYYY',
- 'LLL' => 'DD. MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, DD. MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[täna] LT',
- 'nextDay' => '[homme] LT',
- 'lastDay' => '[eile] LT',
- 'nextWeek' => 'dddd LT',
- 'lastWeek' => '[eelmine] dddd LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
- 'months_short' => ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'],
- 'weekdays' => ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'],
- 'weekdays_short' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
- 'weekdays_min' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
- 'list' => [', ', ' ja '],
- 'meridiem' => ['enne lõunat', 'pärast lõunat'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/et.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - JD Isaacks
- */
-return [
- 'year' => 'urte bat|:count urte',
- 'y' => 'Urte 1|:count urte',
- 'month' => 'hilabete bat|:count hilabete',
- 'm' => 'Hile 1|:count hile',
- 'week' => 'Aste 1|:count aste',
- 'w' => 'Aste 1|:count aste',
- 'day' => 'egun bat|:count egun',
- 'd' => 'Egun 1|:count egun',
- 'hour' => 'ordu bat|:count ordu',
- 'h' => 'Ordu 1|:count ordu',
- 'minute' => 'minutu bat|:count minutu',
- 'min' => 'Minutu 1|:count minutu',
- 'second' => 'segundo batzuk|:count segundo',
- 's' => 'Segundu 1|:count segundu',
- 'ago' => 'duela :time',
- 'from_now' => ':time barru',
- 'after' => ':time geroago',
- 'before' => ':time lehenago',
- 'diff_yesterday' => 'atzo',
- 'diff_tomorrow' => 'bihar',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'YYYY[ko] MMMM[ren] D[a]',
- 'LLL' => 'YYYY[ko] MMMM[ren] D[a] HH:mm',
- 'LLLL' => 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[gaur] LT[etan]',
- 'nextDay' => '[bihar] LT[etan]',
- 'nextWeek' => 'dddd LT[etan]',
- 'lastDay' => '[atzo] LT[etan]',
- 'lastWeek' => '[aurreko] dddd LT[etan]',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['urtarrila', 'otsaila', 'martxoa', 'apirila', 'maiatza', 'ekaina', 'uztaila', 'abuztua', 'iraila', 'urria', 'azaroa', 'abendua'],
- 'months_short' => ['urt.', 'ots.', 'mar.', 'api.', 'mai.', 'eka.', 'uzt.', 'abu.', 'ira.', 'urr.', 'aza.', 'abe.'],
- 'weekdays' => ['igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna', 'ostirala', 'larunbata'],
- 'weekdays_short' => ['ig.', 'al.', 'ar.', 'az.', 'og.', 'ol.', 'lr.'],
- 'weekdays_min' => ['ig', 'al', 'ar', 'az', 'og', 'ol', 'lr'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' eta '],
- 'meridiem' => ['g', 'a'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/eu.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['kíkíríg', 'ngəgógəle'],
- 'weekdays' => ['sɔ́ndɔ', 'mɔ́ndi', 'sɔ́ndɔ məlú mə́bɛ̌', 'sɔ́ndɔ məlú mə́lɛ́', 'sɔ́ndɔ məlú mə́nyi', 'fúladé', 'séradé'],
- 'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
- 'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
- 'months' => ['ngɔn osú', 'ngɔn bɛ̌', 'ngɔn lála', 'ngɔn nyina', 'ngɔn tána', 'ngɔn saməna', 'ngɔn zamgbála', 'ngɔn mwom', 'ngɔn ebulú', 'ngɔn awóm', 'ngɔn awóm ai dziá', 'ngɔn awóm ai bɛ̌'],
- 'months_short' => ['ngo', 'ngb', 'ngl', 'ngn', 'ngt', 'ngs', 'ngz', 'ngm', 'nge', 'nga', 'ngad', 'ngab'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- // Too unreliable
- /*
- 'year' => ':count mbu', // less reliable
- 'y' => ':count mbu', // less reliable
- 'a_year' => ':count mbu', // less reliable
-
- 'month' => ':count ngòn', // less reliable
- 'm' => ':count ngòn', // less reliable
- 'a_month' => ':count ngòn', // less reliable
-
- 'week' => ':count mësë', // less reliable
- 'w' => ':count mësë', // less reliable
- 'a_week' => ':count mësë', // less reliable
-
- 'day' => ':count mësë', // less reliable
- 'd' => ':count mësë', // less reliable
- 'a_day' => ':count mësë', // less reliable
-
- 'hour' => ':count awola', // less reliable
- 'h' => ':count awola', // less reliable
- 'a_hour' => ':count awola', // less reliable
-
- 'minute' => ':count awola', // less reliable
- 'min' => ':count awola', // less reliable
- 'a_minute' => ':count awola', // less reliable
- */
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Josh Soref
- * - François B
- * - Nasser Ghiasi
- * - JD Isaacks
- * - Hossein Jabbari
- * - nimamo
- * - hafezdivandari
- */
-return [
- 'year' => ':count سال',
- 'a_year' => 'یک سال'.'|:count '.'سال',
- 'y' => ':count سال',
- 'month' => ':count ماه',
- 'a_month' => 'یک ماه'.'|:count '.'ماه',
- 'm' => ':count ماه',
- 'week' => ':count هفته',
- 'a_week' => 'یک هفته'.'|:count '.'هفته',
- 'w' => ':count هفته',
- 'day' => ':count روز',
- 'a_day' => 'یک روز'.'|:count '.'روز',
- 'd' => ':count روز',
- 'hour' => ':count ساعت',
- 'a_hour' => 'یک دقیقهیک ساعت'.'|:count '.'ساعت',
- 'h' => ':count ساعت',
- 'minute' => ':count دقیقه',
- 'a_minute' => 'یک دقیقه'.'|:count '.'دقیقه',
- 'min' => ':count دقیقه',
- 'second' => ':count ثانیه|چند ثانیه',
- 's' => ':count ثانیه',
- 'ago' => ':time پیش',
- 'from_now' => 'در :time',
- 'after' => ':time پس از',
- 'before' => ':time پیش از',
- 'formats' => [
- 'LT' => 'OH:Om',
- 'LTS' => 'OH:Om:Os',
- 'L' => 'OD/OM/OY',
- 'LL' => 'OD MMMM OY',
- 'LLL' => 'OD MMMM OY OH:Om',
- 'LLLL' => 'dddd, OD MMMM OY OH:Om',
- ],
- 'calendar' => [
- 'sameDay' => '[امروز ساعت] LT',
- 'nextDay' => '[فردا ساعت] LT',
- 'nextWeek' => 'dddd [ساعت] LT',
- 'lastDay' => '[دیروز ساعت] LT',
- 'lastWeek' => 'dddd [پیش] [ساعت] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':timeم',
- 'meridiem' => ['قبل از ظهر', 'بعد از ظهر'],
- 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
- 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
- 'weekdays' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
- 'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
- 'weekdays_min' => ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'list' => ['، ', ' و '],
- 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
- 'months_short_standalone' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
- 'weekend' => [5, 5],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fa.php', [
- 'meridiem' => ['ق', 'ب'],
- 'weekend' => [4, 5],
- 'formats' => [
- 'L' => 'OY/OM/OD',
- 'LL' => 'OD MMM OY',
- 'LLL' => 'OD MMMM OY، H:mm',
- 'LLLL' => 'dddd OD MMMM OY، H:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fa.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'months' => ['siilo', 'colte', 'mbooy', 'seeɗto', 'duujal', 'korse', 'morso', 'juko', 'siilto', 'yarkomaa', 'jolal', 'bowte'],
- 'months_short' => ['sii', 'col', 'mbo', 'see', 'duu', 'kor', 'mor', 'juk', 'slt', 'yar', 'jol', 'bow'],
- 'weekdays' => ['dewo', 'aaɓnde', 'mawbaare', 'njeslaare', 'naasaande', 'mawnde', 'hoore-biir'],
- 'weekdays_short' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
- 'weekdays_min' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['subaka', 'kikiiɗe'],
-
- 'year' => ':count baret', // less reliable
- 'y' => ':count baret', // less reliable
- 'a_year' => ':count baret', // less reliable
-
- 'month' => ':count lewru', // less reliable
- 'm' => ':count lewru', // less reliable
- 'a_month' => ':count lewru', // less reliable
-
- 'week' => ':count naange', // less reliable
- 'w' => ':count naange', // less reliable
- 'a_week' => ':count naange', // less reliable
-
- 'day' => ':count dian', // less reliable
- 'd' => ':count dian', // less reliable
- 'a_day' => ':count dian', // less reliable
-
- 'hour' => ':count montor', // less reliable
- 'h' => ':count montor', // less reliable
- 'a_hour' => ':count montor', // less reliable
-
- 'minute' => ':count tokossuoum', // less reliable
- 'min' => ':count tokossuoum', // less reliable
- 'a_minute' => ':count tokossuoum', // less reliable
-
- 'second' => ':count tenen', // less reliable
- 's' => ':count tenen', // less reliable
- 'a_second' => ':count tenen', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ff.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ff.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ff.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Pular-Fulfulde.org Ibrahima Sarr admin@pulaar-fulfulde.org
- */
-return require __DIR__.'/ff.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Janne Warén
- * - digitalfrost
- * - Tsutomu Kuroda
- * - Roope Salmi
- * - tjku
- * - Max Melentiev
- * - Sami Haahtinen
- * - Teemu Leisti
- * - Artem Ignatyev
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Robert Bjarnason
- * - Aaron Patterson
- * - Nicolás Hock Isaza
- * - Tom Hughes
- * - Sven Fuchs
- * - Petri Kivikangas
- * - Nizar Jouini
- * - Marko Seppae
- * - Tomi Mynttinen (Pikseli)
- */
-return [
- 'year' => ':count vuosi|:count vuotta',
- 'y' => ':count v',
- 'month' => ':count kuukausi|:count kuukautta',
- 'm' => ':count kk',
- 'week' => ':count viikko|:count viikkoa',
- 'w' => ':count vk',
- 'day' => ':count päivä|:count päivää',
- 'd' => ':count pv',
- 'hour' => ':count tunti|:count tuntia',
- 'h' => ':count t',
- 'minute' => ':count minuutti|:count minuuttia',
- 'min' => ':count min',
- 'second' => ':count sekunti|:count sekuntia',
- 's' => ':count s',
- 'ago' => ':time sitten',
- 'from_now' => ':time tästä hetkestä',
- 'after' => ':time sen jälkeen',
- 'before' => ':time ennen',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' ja '],
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm:ss',
- 'L' => 'D.M.YYYY',
- 'LL' => 'dddd D. MMMM[ta] YYYY',
- 'LLL' => 'D.MM. HH.mm',
- 'LLLL' => 'D. MMMM[ta] YYYY HH.mm',
- ],
- 'weekdays' => ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'],
- 'weekdays_short' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
- 'weekdays_min' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
- 'months' => ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'],
- 'months_short' => ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä', 'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'],
- 'meridiem' => ['aamupäivä', 'iltapäivä'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fi.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/fil_PH.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Rene Torres Rene Torres, Pablo Saratxaga rgtorre@rocketmail.com, pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'MM/DD/YY',
- ],
- 'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
- 'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
- 'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkoles', 'Huwebes', 'Biyernes', 'Sabado'],
- 'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
- 'weekdays_min' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['N.U.', 'N.H.'],
-
- 'year' => ':count gulang',
- 'y' => ':count gulang',
- 'a_year' => ':count gulang',
-
- 'month' => ':count buwan',
- 'm' => ':count buwan',
- 'a_month' => ':count buwan',
-
- 'week' => ':count linggo',
- 'w' => ':count linggo',
- 'a_week' => ':count linggo',
-
- 'day' => ':count araw',
- 'd' => ':count araw',
- 'a_day' => ':count araw',
-
- 'hour' => ':count oras',
- 'h' => ':count oras',
- 'a_hour' => ':count oras',
-
- 'minute' => ':count minuto',
- 'min' => ':count minuto',
- 'a_minute' => ':count minuto',
-
- 'second' => ':count ulit',
- 's' => ':count ulit',
- 'a_second' => ':count ulit',
-
- 'ago' => ':time ang nakalipas',
- 'from_now' => 'sa :time',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kristian Sakarisson
- * - François B
- * - JD Isaacks
- * - Sverri Mohr Olsen
- */
-return [
- 'year' => 'eitt ár|:count ár',
- 'y' => ':count ár|:count ár',
- 'month' => 'ein mánaði|:count mánaðir',
- 'm' => ':count mánaður|:count mánaðir',
- 'week' => ':count vika|:count vikur',
- 'w' => ':count vika|:count vikur',
- 'day' => 'ein dagur|:count dagar',
- 'd' => ':count dag|:count dagar',
- 'hour' => 'ein tími|:count tímar',
- 'h' => ':count tími|:count tímar',
- 'minute' => 'ein minutt|:count minuttir',
- 'min' => ':count minutt|:count minuttir',
- 'second' => 'fá sekund|:count sekundir',
- 's' => ':count sekund|:count sekundir',
- 'ago' => ':time síðani',
- 'from_now' => 'um :time',
- 'after' => ':time aftaná',
- 'before' => ':time áðrenn',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D. MMMM, YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Í dag kl.] LT',
- 'nextDay' => '[Í morgin kl.] LT',
- 'nextWeek' => 'dddd [kl.] LT',
- 'lastDay' => '[Í gjár kl.] LT',
- 'lastWeek' => '[síðstu] dddd [kl] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['januar', 'februar', 'mars', 'apríl', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
- 'weekdays' => ['sunnudagur', 'mánadagur', 'týsdagur', 'mikudagur', 'hósdagur', 'fríggjadagur', 'leygardagur'],
- 'weekdays_short' => ['sun', 'mán', 'týs', 'mik', 'hós', 'frí', 'ley'],
- 'weekdays_min' => ['su', 'má', 'tý', 'mi', 'hó', 'fr', 'le'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' og '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fo.php', [
- 'formats' => [
- 'L' => 'DD.MM.yy',
- 'LL' => 'DD.MM.YYYY',
- 'LLL' => 'D. MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY, HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fo.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Dieter Sting
- * - François B
- * - Maxime VALY
- * - JD Isaacks
- * - Dieter Sting
- * - François B
- * - JD Isaacks
- * - Sebastian Thierer
- * - Fastfuel
- */
-return [
- 'year' => ':count an|:count ans',
- 'a_year' => 'un an|:count ans',
- 'y' => ':count an|:count ans',
- 'month' => ':count mois|:count mois',
- 'a_month' => 'un mois|:count mois',
- 'm' => ':count mois',
- 'week' => ':count semaine|:count semaines',
- 'a_week' => 'une semaine|:count semaines',
- 'w' => ':count sem.',
- 'day' => ':count jour|:count jours',
- 'a_day' => 'un jour|:count jours',
- 'd' => ':count j',
- 'hour' => ':count heure|:count heures',
- 'a_hour' => 'une heure|:count heures',
- 'h' => ':count h',
- 'minute' => ':count minute|:count minutes',
- 'a_minute' => 'une minute|:count minutes',
- 'min' => ':count min',
- 'second' => ':count seconde|:count secondes',
- 'a_second' => 'quelques secondes|:count secondes',
- 's' => ':count s',
- 'ago' => 'il y a :time',
- 'from_now' => 'dans :time',
- 'after' => ':time après',
- 'before' => ':time avant',
- 'diff_now' => 'à l\'instant',
- 'diff_yesterday' => 'hier',
- 'diff_tomorrow' => 'demain',
- 'diff_before_yesterday' => 'avant-hier',
- 'diff_after_tomorrow' => 'après-demain',
- 'period_recurrences' => ':count fois',
- 'period_interval' => 'tous les :interval',
- 'period_start_date' => 'de :date',
- 'period_end_date' => 'à :date',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Aujourd’hui à] LT',
- 'nextDay' => '[Demain à] LT',
- 'nextWeek' => 'dddd [à] LT',
- 'lastDay' => '[Hier à] LT',
- 'lastWeek' => 'dddd [dernier à] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
- 'months_short' => ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],
- 'weekdays' => ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
- 'weekdays_short' => ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
- 'weekdays_min' => ['di', 'lu', 'ma', 'me', 'je', 've', 'sa'],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- // In french, only the first has be ordinal, other number remains cardinal
- // @link https://fr.wikihow.com/%C3%A9crire-la-date-en-fran%C3%A7ais
- case 'D':
- return $number.($number === 1 ? 'er' : '');
-
- default:
- case 'M':
- case 'Q':
- case 'DDD':
- case 'd':
- return $number.($number === 1 ? 'er' : 'e');
-
- // Words with feminine grammatical gender: semaine
- case 'w':
- case 'W':
- return $number.($number === 1 ? 're' : 'e');
- }
- },
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' et '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'months_short' => ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jui', 'aoû', 'sep', 'oct', 'nov', 'déc'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Dieter Sting
- * - François B
- * - Maxime VALY
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Dieter Sting
- * - François B
- * - Gaspard Bucher
- * - Maxime VALY
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'meridiem' => ['mat.', 'soir'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'first_day_of_week' => 6,
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months_short' => ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jui', 'aoû', 'sep', 'oct', 'nov', 'déc'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'weekend' => [5, 6],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fr.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/fr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/fur_IT.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Pablo Saratxaga pablo@mandrakesoft.com
- */
-return [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD. MM. YY',
- 'LL' => 'DD di MMMM dal YYYY',
- 'LLL' => 'DD di MMM HH:mm',
- 'LLLL' => 'DD di MMMM dal YYYY HH:mm',
- ],
- 'months' => ['zenâr', 'fevrâr', 'març', 'avrîl', 'mai', 'jugn', 'lui', 'avost', 'setembar', 'otubar', 'novembar', 'dicembar'],
- 'months_short' => ['zen', 'fev', 'mar', 'avr', 'mai', 'jug', 'lui', 'avo', 'set', 'otu', 'nov', 'dic'],
- 'weekdays' => ['domenie', 'lunis', 'martars', 'miercus', 'joibe', 'vinars', 'sabide'],
- 'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
- 'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'year' => ':count an',
- 'month' => ':count mês',
- 'week' => ':count setemane',
- 'day' => ':count zornade',
- 'hour' => ':count ore',
- 'minute' => ':count minût',
- 'second' => ':count secont',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Tim Fish
- * - JD Isaacks
- */
-return [
- 'year' => ':count jier|:count jierren',
- 'a_year' => 'ien jier|:count jierren',
- 'y' => ':count j',
- 'month' => ':count moanne|:count moannen',
- 'a_month' => 'ien moanne|:count moannen',
- 'm' => ':count moa.',
- 'week' => ':count wike|:count wiken',
- 'a_week' => 'in wike|:count wiken',
- 'a' => ':count w.',
- 'day' => ':count dei|:count dagen',
- 'a_day' => 'ien dei|:count dagen',
- 'd' => ':count d.',
- 'hour' => ':count oere|:count oeren',
- 'a_hour' => 'ien oere|:count oeren',
- 'h' => ':count o.',
- 'minute' => ':count minút|:count minuten',
- 'a_minute' => 'ien minút|:count minuten',
- 'min' => ':count min.',
- 'second' => ':count sekonde|:count sekonden',
- 'a_second' => 'in pear sekonden|:count sekonden',
- 's' => ':count s.',
- 'ago' => ':time lyn',
- 'from_now' => 'oer :time',
- 'diff_yesterday' => 'juster',
- 'diff_tomorrow' => 'moarn',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD-MM-YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[hjoed om] LT',
- 'nextDay' => '[moarn om] LT',
- 'nextWeek' => 'dddd [om] LT',
- 'lastDay' => '[juster om] LT',
- 'lastWeek' => '[ôfrûne] dddd [om] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
- },
- 'months' => ['jannewaris', 'febrewaris', 'maart', 'april', 'maaie', 'juny', 'july', 'augustus', 'septimber', 'oktober', 'novimber', 'desimber'],
- 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
- 'mmm_suffix' => '.',
- 'weekdays' => ['snein', 'moandei', 'tiisdei', 'woansdei', 'tongersdei', 'freed', 'sneon'],
- 'weekdays_short' => ['si.', 'mo.', 'ti.', 'wo.', 'to.', 'fr.', 'so.'],
- 'weekdays_min' => ['Si', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'So'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' en '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'],
- 'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'],
- 'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'],
- 'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
- 'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/fy.php', [
- 'formats' => [
- 'L' => 'DD-MM-YY',
- ],
- 'months' => ['Jannewaris', 'Febrewaris', 'Maart', 'April', 'Maaie', 'Juny', 'July', 'Augustus', 'Septimber', 'Oktober', 'Novimber', 'Desimber'],
- 'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Snein', 'Moandei', 'Tiisdei', 'Woansdei', 'Tongersdei', 'Freed', 'Sneon'],
- 'weekdays_short' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'],
- 'weekdays_min' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Thanks to André Silva : https://github.com/askpt
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'ga');
-
-return [
- 'year' => ':count bliain',
- 'a_year' => 'bliain|:count bliain',
- 'y' => ':countb',
- 'month' => ':count mí',
- 'a_month' => 'mí|:count mí',
- 'm' => ':countm',
- 'week' => ':count sheachtain',
- 'a_week' => 'sheachtain|:count sheachtain',
- 'w' => ':countsh',
- 'day' => ':count lá',
- 'a_day' => 'lá|:count lá',
- 'd' => ':countl',
- 'hour' => ':count uair an chloig',
- 'a_hour' => 'uair an chloig|:count uair an chloig',
- 'h' => ':countu',
- 'minute' => ':count nóiméad',
- 'a_minute' => 'nóiméad|:count nóiméad',
- 'min' => ':countn',
- 'second' => ':count soicind',
- 'a_second' => 'cúpla soicind|:count soicind',
- 's' => ':countso',
- 'ago' => ':time ó shin',
- 'from_now' => 'i :time',
- 'after' => ':time tar éis',
- 'before' => ':time roimh',
- 'diff_yesterday' => 'inné',
- 'diff_tomorrow' => 'amárach',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Inniu ag] LT',
- 'nextDay' => '[Amárach ag] LT',
- 'nextWeek' => 'dddd [ag] LT',
- 'lastDay' => '[Inné aig] LT',
- 'lastWeek' => 'dddd [seo caite] [ag] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Méitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deaireadh Fómhair', 'Samhain', 'Nollaig'],
- 'months_short' => ['Eaná', 'Feab', 'Márt', 'Aibr', 'Beal', 'Méit', 'Iúil', 'Lúna', 'Meán', 'Deai', 'Samh', 'Noll'],
- 'weekdays' => ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Satharn'],
- 'weekdays_short' => ['Dom', 'Lua', 'Mái', 'Céa', 'Déa', 'hAo', 'Sat'],
- 'weekdays_min' => ['Do', 'Lu', 'Má', 'Ce', 'Dé', 'hA', 'Sa'],
- 'ordinal' => function ($number) {
- return $number.($number === 1 ? 'd' : $number % 10 === 2 ? 'na' : 'mh');
- },
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' agus '],
- 'meridiem' => ['r.n.', 'i.n.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ga.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'gd');
-
-/*
- * Authors:
- * - François B
- * - Jon Ashdown
- */
-return [
- 'year' => ':count bliadhna',
- 'a_year' => 'bliadhna|:count bliadhna',
- 'y' => ':count b.',
- 'month' => ':count mìosan',
- 'a_month' => 'mìos|:count mìosan',
- 'm' => ':count ms.',
- 'week' => ':count seachdainean',
- 'a_week' => 'seachdain|:count seachdainean',
- 'w' => ':count s.',
- 'day' => ':count latha',
- 'a_day' => 'latha|:count latha',
- 'd' => ':count l.',
- 'hour' => ':count uairean',
- 'a_hour' => 'uair|:count uairean',
- 'h' => ':count u.',
- 'minute' => ':count mionaidean',
- 'a_minute' => 'mionaid|:count mionaidean',
- 'min' => ':count md.',
- 'second' => ':count diogan',
- 'a_second' => 'beagan diogan|:count diogan',
- 's' => ':count d.',
- 'ago' => 'bho chionn :time',
- 'from_now' => 'ann an :time',
- 'diff_yesterday' => 'An-dè',
- 'diff_tomorrow' => 'A-màireach',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[An-diugh aig] LT',
- 'nextDay' => '[A-màireach aig] LT',
- 'nextWeek' => 'dddd [aig] LT',
- 'lastDay' => '[An-dè aig] LT',
- 'lastWeek' => 'dddd [seo chaidh] [aig] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- return $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh'));
- },
- 'months' => ['Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'],
- 'months_short' => ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'],
- 'weekdays' => ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'],
- 'weekdays_short' => ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'],
- 'weekdays_min' => ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' agus '],
- 'meridiem' => ['m', 'f'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/gd.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/gez_ER.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባት', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'],
- 'months_short' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባ', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'],
- 'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'],
- 'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
- 'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ጽባሕ', 'ምሴት'],
-
- 'month' => ':count ወርሕ', // less reliable
- 'm' => ':count ወርሕ', // less reliable
- 'a_month' => ':count ወርሕ', // less reliable
-
- 'week' => ':count ሰብዑ', // less reliable
- 'w' => ':count ሰብዑ', // less reliable
- 'a_week' => ':count ሰብዑ', // less reliable
-
- 'hour' => ':count አንትሙ', // less reliable
- 'h' => ':count አንትሙ', // less reliable
- 'a_hour' => ':count አንትሙ', // less reliable
-
- 'minute' => ':count ንኡስ', // less reliable
- 'min' => ':count ንኡስ', // less reliable
- 'a_minute' => ':count ንኡስ', // less reliable
-
- 'year' => ':count ዓመት',
- 'y' => ':count ዓመት',
- 'a_year' => ':count ዓመት',
-
- 'day' => ':count ዕለት',
- 'd' => ':count ዕለት',
- 'a_day' => ':count ዕለት',
-
- 'second' => ':count ካልእ',
- 's' => ':count ካልእ',
- 'a_second' => ':count ካልእ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
- 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
- 'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'],
- 'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
- 'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ጽባሕ', 'ምሴት'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - François B
- * - Fidel Pita
- * - JD Isaacks
- * - Diego Vilariño
- * - Sebastian Thierer
- */
-return [
- 'year' => ':count ano|:count anos',
- 'a_year' => 'un ano|:count anos',
- 'y' => ':count a.',
- 'month' => ':count mes|:count meses',
- 'a_month' => 'un mes|:count meses',
- 'm' => ':count mes.',
- 'week' => ':count semana|:count semanas',
- 'a_week' => 'unha semana|:count semanas',
- 'w' => ':count sem.',
- 'day' => ':count día|:count días',
- 'a_day' => 'un día|:count días',
- 'd' => ':count d.',
- 'hour' => ':count hora|:count horas',
- 'a_hour' => 'unha hora|:count horas',
- 'h' => ':count h.',
- 'minute' => ':count minuto|:count minutos',
- 'a_minute' => 'un minuto|:count minutos',
- 'min' => ':count min.',
- 'second' => ':count segundo|:count segundos',
- 'a_second' => 'uns segundos|:count segundos',
- 's' => ':count seg.',
- 'ago' => 'hai :time',
- 'from_now' => function ($time) {
- if (substr($time, 0, 2) === 'un') {
- return "n$time";
- }
-
- return "en $time";
- },
- 'after' => ':time despois',
- 'before' => ':time antes',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D [de] MMMM [de] YYYY',
- 'LLL' => 'D [de] MMMM [de] YYYY H:mm',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => function (\Carbon\CarbonInterface $current) {
- return '[hoxe '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
- },
- 'nextDay' => function (\Carbon\CarbonInterface $current) {
- return '[mañá '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
- },
- 'nextWeek' => function (\Carbon\CarbonInterface $current) {
- return 'dddd ['.($current->hour !== 1 ? 'ás' : 'á').'] LT';
- },
- 'lastDay' => function (\Carbon\CarbonInterface $current) {
- return '[onte '.($current->hour !== 1 ? 'á' : 'a').'] LT';
- },
- 'lastWeek' => function (\Carbon\CarbonInterface $current) {
- return '[o] dddd [pasado '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberº',
- 'months' => ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo', 'agosto', 'setembro', 'outubro', 'novembro', 'decembro'],
- 'months_short' => ['xan.', 'feb.', 'mar.', 'abr.', 'mai.', 'xuñ.', 'xul.', 'ago.', 'set.', 'out.', 'nov.', 'dec.'],
- 'weekdays' => ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado'],
- 'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mér.', 'xov.', 'ven.', 'sáb.'],
- 'weekdays_min' => ['do', 'lu', 'ma', 'mé', 'xo', 've', 'sá'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' e '],
- 'meridiem' => ['a.m.', 'p.m.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/gl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/gom_Latn.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return [
- 'year' => ':count voros|:count vorsam',
- 'y' => ':countv',
- 'month' => ':count mhoino|:count mhoine',
- 'm' => ':countmh',
- 'week' => ':count satolleacho|:count satolleache',
- 'w' => ':countsa|:countsa',
- 'day' => ':count dis',
- 'd' => ':countd',
- 'hour' => ':count hor|:count horam',
- 'h' => ':counth',
- 'minute' => ':count minute|:count mintam',
- 'min' => ':countm',
- 'second' => ':count second',
- 's' => ':counts',
-
- 'formats' => [
- 'LT' => 'A h:mm [vazta]',
- 'LTS' => 'A h:mm:ss [vazta]',
- 'L' => 'DD-MM-YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY A h:mm [vazta]',
- 'LLLL' => 'dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]',
- 'llll' => 'ddd, D MMM YYYY, A h:mm [vazta]',
- ],
-
- 'calendar' => [
- 'sameDay' => '[Aiz] LT',
- 'nextDay' => '[Faleam] LT',
- 'nextWeek' => '[Ieta to] dddd[,] LT',
- 'lastDay' => '[Kal] LT',
- 'lastWeek' => '[Fatlo] dddd[,] LT',
- 'sameElse' => 'L',
- ],
-
- 'months' => ['Janer', 'Febrer', 'Mars', 'Abril', 'Mai', 'Jun', 'Julai', 'Agost', 'Setembr', 'Otubr', 'Novembr', 'Dezembr'],
- 'months_short' => ['Jan.', 'Feb.', 'Mars', 'Abr.', 'Mai', 'Jun', 'Jul.', 'Ago.', 'Set.', 'Otu.', 'Nov.', 'Dez.'],
- 'weekdays' => ['Aitar', 'Somar', 'Mongllar', 'Budvar', 'Brestar', 'Sukrar', 'Son\'var'],
- 'weekdays_short' => ['Ait.', 'Som.', 'Mon.', 'Bud.', 'Bre.', 'Suk.', 'Son.'],
- 'weekdays_min' => ['Ai', 'Sm', 'Mo', 'Bu', 'Br', 'Su', 'Sn'],
-
- 'ordinal' => function ($number, $period) {
- return $number.($period === 'D' ? 'er' : '');
- },
-
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'rati';
- }
- if ($hour < 12) {
- return 'sokalli';
- }
- if ($hour < 16) {
- return 'donparam';
- }
- if ($hour < 20) {
- return 'sanje';
- }
-
- return 'rati';
- },
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' ani '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Christopher Dell
- * - Akira Matsuda
- * - Enrique Vidal
- * - Simone Carletti
- * - Henning Kiel
- * - Aaron Patterson
- * - Florian Hanke
- */
-return [
- 'year' => ':count Johr',
- 'month' => ':count Monet',
- 'week' => ':count Woche',
- 'day' => ':count Tag',
- 'hour' => ':count Schtund',
- 'minute' => ':count Minute',
- 'second' => ':count Sekunde',
- 'weekdays' => ['Sunntig', 'Mäntig', 'Ziischtig', 'Mittwuch', 'Dunschtig', 'Friitig', 'Samschtig'],
- 'weekdays_short' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'],
- 'weekdays_min' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'],
- 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'September', 'Oktober', 'November', 'Dezember'],
- 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
- 'meridiem' => ['am Vormittag', 'am Namittag'],
- 'ordinal' => ':number.',
- 'list' => [', ', ' und '],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'Do MMMM YYYY',
- 'LLL' => 'Do MMMM, HH:mm [Uhr]',
- 'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]',
- ],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/gsw.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/gsw.php', [
- 'meridiem' => ['vorm.', 'nam.'],
- 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LLL' => 'Do MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, Do MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/gsw.php', [
- 'meridiem' => ['vorm.', 'nam.'],
- 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LLL' => 'Do MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, Do MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Kaushik Thanki
- * - Josh Soref
- */
-return [
- 'year' => 'એક વર્ષ|:count વર્ષ',
- 'y' => ':countવર્ષ|:countવર્ષો',
- 'month' => 'એક મહિનો|:count મહિનો',
- 'm' => ':countમહિનો|:countમહિના',
- 'week' => ':count અઠવાડિયું|:count અઠવાડિયા',
- 'w' => ':countઅઠ.|:countઅઠ.',
- 'day' => 'એક દિવસ|:count દિવસ',
- 'd' => ':countદિ.|:countદિ.',
- 'hour' => 'એક કલાક|:count કલાક',
- 'h' => ':countક.|:countક.',
- 'minute' => 'એક મિનિટ|:count મિનિટ',
- 'min' => ':countમિ.|:countમિ.',
- 'second' => 'અમુક પળો|:count સેકંડ',
- 's' => ':countસે.|:countસે.',
- 'ago' => ':time પેહલા',
- 'from_now' => ':time મા',
- 'after' => ':time પછી',
- 'before' => ':time પહેલા',
- 'diff_yesterday' => 'ગઇકાલે',
- 'diff_tomorrow' => 'કાલે',
- 'formats' => [
- 'LT' => 'A h:mm વાગ્યે',
- 'LTS' => 'A h:mm:ss વાગ્યે',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm વાગ્યે',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm વાગ્યે',
- ],
- 'calendar' => [
- 'sameDay' => '[આજ] LT',
- 'nextDay' => '[કાલે] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[ગઇકાલે] LT',
- 'lastWeek' => '[પાછલા] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'રાત';
- }
- if ($hour < 10) {
- return 'સવાર';
- }
- if ($hour < 17) {
- return 'બપોર';
- }
- if ($hour < 20) {
- return 'સાંજ';
- }
-
- return 'રાત';
- },
- 'months' => ['જાન્યુઆરી', 'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર', 'ઑક્ટ્બર', 'નવેમ્બર', 'ડિસેમ્બર'],
- 'months_short' => ['જાન્યુ.', 'ફેબ્રુ.', 'માર્ચ', 'એપ્રિ.', 'મે', 'જૂન', 'જુલા.', 'ઑગ.', 'સપ્ટે.', 'ઑક્ટ્.', 'નવે.', 'ડિસે.'],
- 'weekdays' => ['રવિવાર', 'સોમવાર', 'મંગળવાર', 'બુધ્વાર', 'ગુરુવાર', 'શુક્રવાર', 'શનિવાર'],
- 'weekdays_short' => ['રવિ', 'સોમ', 'મંગળ', 'બુધ્', 'ગુરુ', 'શુક્ર', 'શનિ'],
- 'weekdays_min' => ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ', 'શ'],
- 'list' => [', ', ' અને '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/gu.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Ma', 'Mo'],
- 'weekdays' => ['Chumapiri', 'Chumatato', 'Chumaine', 'Chumatano', 'Aramisi', 'Ichuma', 'Esabato'],
- 'weekdays_short' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
- 'weekdays_min' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
- 'months' => ['Chanuari', 'Feburari', 'Machi', 'Apiriri', 'Mei', 'Juni', 'Chulai', 'Agosti', 'Septemba', 'Okitoba', 'Nobemba', 'Disemba'],
- 'months_short' => ['Can', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Cul', 'Agt', 'Sep', 'Okt', 'Nob', 'Dis'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'month' => ':count omotunyi', // less reliable
- 'm' => ':count omotunyi', // less reliable
- 'a_month' => ':count omotunyi', // less reliable
-
- 'week' => ':count isano naibere', // less reliable
- 'w' => ':count isano naibere', // less reliable
- 'a_week' => ':count isano naibere', // less reliable
-
- 'second' => ':count ibere', // less reliable
- 's' => ':count ibere', // less reliable
- 'a_second' => ':count ibere', // less reliable
-
- 'year' => ':count omwaka',
- 'y' => ':count omwaka',
- 'a_year' => ':count omwaka',
-
- 'day' => ':count rituko',
- 'd' => ':count rituko',
- 'a_day' => ':count rituko',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/gv_GB.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Alastair McKinstry bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Jerrey-geuree', 'Toshiaght-arree', 'Mayrnt', 'Averil', 'Boaldyn', 'Mean-souree', 'Jerrey-souree', 'Luanistyn', 'Mean-fouyir', 'Jerrey-fouyir', 'Mee Houney', 'Mee ny Nollick'],
- 'months_short' => ['J-guer', 'T-arree', 'Mayrnt', 'Avrril', 'Boaldyn', 'M-souree', 'J-souree', 'Luanistyn', 'M-fouyir', 'J-fouyir', 'M.Houney', 'M.Nollick'],
- 'weekdays' => ['Jedoonee', 'Jelhein', 'Jemayrt', 'Jercean', 'Jerdein', 'Jeheiney', 'Jesarn'],
- 'weekdays_short' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
- 'weekdays_min' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count blein',
- 'y' => ':count blein',
- 'a_year' => ':count blein',
-
- 'month' => ':count mee',
- 'm' => ':count mee',
- 'a_month' => ':count mee',
-
- 'week' => ':count shiaghtin',
- 'w' => ':count shiaghtin',
- 'a_week' => ':count shiaghtin',
-
- 'day' => ':count laa',
- 'd' => ':count laa',
- 'a_day' => ':count laa',
-
- 'hour' => ':count oor',
- 'h' => ':count oor',
- 'a_hour' => ':count oor',
-
- 'minute' => ':count feer veg',
- 'min' => ':count feer veg',
- 'a_minute' => ':count feer veg',
-
- 'second' => ':count derrey',
- 's' => ':count derrey',
- 'a_second' => ':count derrey',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - pablo@mandriva.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM, YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM, YYYY HH:mm',
- ],
- 'months' => ['Janairu', 'Faburairu', 'Maris', 'Afirilu', 'Mayu', 'Yuni', 'Yuli', 'Agusta', 'Satumba', 'Oktoba', 'Nuwamba', 'Disamba'],
- 'months_short' => ['Jan', 'Fab', 'Mar', 'Afi', 'May', 'Yun', 'Yul', 'Agu', 'Sat', 'Okt', 'Nuw', 'Dis'],
- 'weekdays' => ['Lahadi', 'Litini', 'Talata', 'Laraba', 'Alhamis', 'Jumaʼa', 'Asabar'],
- 'weekdays_short' => ['Lah', 'Lit', 'Tal', 'Lar', 'Alh', 'Jum', 'Asa'],
- 'weekdays_min' => ['Lh', 'Li', 'Ta', 'Lr', 'Al', 'Ju', 'As'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => 'shekara :count',
- 'y' => 'shekara :count',
- 'a_year' => 'shekara :count',
-
- 'month' => ':count wátàa',
- 'm' => ':count wátàa',
- 'a_month' => ':count wátàa',
-
- 'week' => ':count mako',
- 'w' => ':count mako',
- 'a_week' => ':count mako',
-
- 'day' => ':count rana',
- 'd' => ':count rana',
- 'a_day' => ':count rana',
-
- 'hour' => ':count áwàa',
- 'h' => ':count áwàa',
- 'a_hour' => ':count áwàa',
-
- 'minute' => 'minti :count',
- 'min' => 'minti :count',
- 'a_minute' => 'minti :count',
-
- 'second' => ':count ná bíyú',
- 's' => ':count ná bíyú',
- 'a_second' => ':count ná bíyú',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ha.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ha.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ha.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/hak_TW.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY年MM月DD日',
- ],
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
- 'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'],
- 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['上晝', '下晝'],
-
- 'year' => ':count ngien11',
- 'y' => ':count ngien11',
- 'a_year' => ':count ngien11',
-
- 'month' => ':count ngie̍t',
- 'm' => ':count ngie̍t',
- 'a_month' => ':count ngie̍t',
-
- 'week' => ':count lî-pai',
- 'w' => ':count lî-pai',
- 'a_week' => ':count lî-pai',
-
- 'day' => ':count ngit',
- 'd' => ':count ngit',
- 'a_day' => ':count ngit',
-
- 'hour' => ':count sṳ̀',
- 'h' => ':count sṳ̀',
- 'a_hour' => ':count sṳ̀',
-
- 'minute' => ':count fûn',
- 'min' => ':count fûn',
- 'a_minute' => ':count fûn',
-
- 'second' => ':count miéu',
- 's' => ':count miéu',
- 'a_second' => ':count miéu',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'months' => ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei', 'Iune', 'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa', 'Kekemapa'],
- 'months_short' => ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.', 'Iul.', 'ʻAu.', 'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
- 'weekdays' => ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu', 'Poʻahā', 'Poʻalima', 'Poʻaono'],
- 'weekdays_short' => ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
- 'weekdays_min' => ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
- ],
-
- 'year' => ':count makahiki',
- 'y' => ':count makahiki',
- 'a_year' => ':count makahiki',
-
- 'month' => ':count mahina',
- 'm' => ':count mahina',
- 'a_month' => ':count mahina',
-
- 'week' => ':count pule',
- 'w' => ':count pule',
- 'a_week' => ':count pule',
-
- 'day' => ':count lā',
- 'd' => ':count lā',
- 'a_day' => ':count lā',
-
- 'hour' => ':count hola',
- 'h' => ':count hola',
- 'a_hour' => ':count hola',
-
- 'minute' => ':count minuke',
- 'min' => ':count minuke',
- 'a_minute' => ':count minuke',
-
- 'second' => ':count lua',
- 's' => ':count lua',
- 'a_second' => ':count lua',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Daniel Cohen Gindi
- * - JD Isaacks
- * - Itai Nathaniel
- * - GabMic
- */
-return [
- 'year' => 'שנה|{2}שנתיים|:count שנים',
- 'y' => 'שנה|{2}שנתיים|:count שנים',
- 'month' => 'חודש|{2}חודשיים|:count חודשים',
- 'm' => 'חודש|{2}חודשיים|:count חודשים',
- 'week' => 'שבוע|{2}שבועיים|:count שבועות',
- 'w' => 'שבוע|{2}שבועיים|:count שבועות',
- 'day' => 'יום|{2}יומיים|:count ימים',
- 'd' => 'יום|{2}יומיים|:count ימים',
- 'hour' => 'שעה|{2}שעתיים|:count שעות',
- 'h' => 'שעה|{2}שעתיים|:count שעות',
- 'minute' => 'דקה|{2}שתי דקות|:count דקות',
- 'min' => 'דקה|{2}שתי דקות|:count דקות',
- 'second' => 'שנייה|:count שניות',
- 'a_second' => 'כמה שניות|:count שניות',
- 's' => 'שניה|:count שניות',
- 'ago' => 'לפני :time',
- 'from_now' => 'בעוד :time מעכשיו',
- 'after' => 'אחרי :time',
- 'before' => 'לפני :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D [ב]MMMM YYYY',
- 'LLL' => 'D [ב]MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D [ב]MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[היום ב־]LT',
- 'nextDay' => '[מחר ב־]LT',
- 'nextWeek' => 'dddd [בשעה] LT',
- 'lastDay' => '[אתמול ב־]LT',
- 'lastWeek' => '[ביום] dddd [האחרון בשעה] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour, $minute, $isLower) {
- if ($hour < 5) {
- return 'לפנות בוקר';
- }
- if ($hour < 10) {
- return 'בבוקר';
- }
- if ($hour < 12) {
- return $isLower ? 'לפנה"צ' : 'לפני הצהריים';
- }
- if ($hour < 18) {
- return $isLower ? 'אחה"צ' : 'אחרי הצהריים';
- }
-
- return 'בערב';
- },
- 'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],
- 'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],
- 'weekdays' => ['ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'],
- 'weekdays_short' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
- 'weekdays_min' => ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש'],
- 'list' => [', ', ' ו -'],
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/he.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - abhimanyu003
- * - Josh Soref
- * - JD Isaacks
- */
-return [
- 'year' => 'एक वर्ष|:count वर्ष',
- 'y' => '1 वर्ष|:count वर्षों',
- 'month' => 'एक महीने|:count महीने',
- 'm' => '1 माह|:count महीने',
- 'week' => '1 सप्ताह|:count सप्ताह',
- 'w' => '1 सप्ताह|:count सप्ताह',
- 'day' => 'एक दिन|:count दिन',
- 'd' => '1 दिन|:count दिनों',
- 'hour' => 'एक घंटा|:count घंटे',
- 'h' => '1 घंटा|:count घंटे',
- 'minute' => 'एक मिनट|:count मिनट',
- 'min' => '1 मिनट|:count मिनटों',
- 'second' => 'कुछ ही क्षण|:count सेकंड',
- 's' => '1 सेकंड|:count सेकंड',
- 'ago' => ':time पहले',
- 'from_now' => ':time में',
- 'after' => ':time के बाद',
- 'before' => ':time के पहले',
- 'diff_yesterday' => 'कल',
- 'diff_tomorrow' => 'कल',
- 'formats' => [
- 'LT' => 'A h:mm बजे',
- 'LTS' => 'A h:mm:ss बजे',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm बजे',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm बजे',
- ],
- 'calendar' => [
- 'sameDay' => '[आज] LT',
- 'nextDay' => '[कल] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[कल] LT',
- 'lastWeek' => '[पिछले] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'रात';
- }
- if ($hour < 10) {
- return 'सुबह';
- }
- if ($hour < 17) {
- return 'दोपहर';
- }
- if ($hour < 20) {
- return 'शाम';
- }
-
- return 'रात';
- },
- 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'months_short' => ['जन.', 'फ़र.', 'मार्च', 'अप्रै.', 'मई', 'जून', 'जुल.', 'अग.', 'सित.', 'अक्टू.', 'नव.', 'दिस.'],
- 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],
- 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरू', 'शुक्र', 'शनि'],
- 'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],
- 'list' => [', ', ' और '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/hi.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/hif_FJ.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'dddd DD MMM YYYY',
- ],
- 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- 'weekdays' => ['Ravivar', 'Somvar', 'Mangalvar', 'Budhvar', 'Guruvar', 'Shukravar', 'Shanivar'],
- 'weekdays_short' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'],
- 'weekdays_min' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'],
- 'meridiem' => ['Purvahan', 'Aparaahna'],
-
- 'hour' => ':count minit', // less reliable
- 'h' => ':count minit', // less reliable
- 'a_hour' => ':count minit', // less reliable
-
- 'year' => ':count saal',
- 'y' => ':count saal',
- 'a_year' => ':count saal',
-
- 'month' => ':count Mahina',
- 'm' => ':count Mahina',
- 'a_month' => ':count Mahina',
-
- 'week' => ':count Hafta',
- 'w' => ':count Hafta',
- 'a_week' => ':count Hafta',
-
- 'day' => ':count Din',
- 'd' => ':count Din',
- 'a_day' => ':count Din',
-
- 'minute' => ':count Minit',
- 'min' => ':count Minit',
- 'a_minute' => ':count Minit',
-
- 'second' => ':count Second',
- 's' => ':count Second',
- 'a_second' => ':count Second',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/hne_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat, Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अपरेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितमबर', 'अकटूबर', 'नवमबर', 'दिसमबर'],
- 'months_short' => ['जन', 'फर', 'मार्च', 'अप', 'मई', 'जून', 'जुला', 'अग', 'सित', 'अकटू', 'नव', 'दिस'],
- 'weekdays' => ['इतवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बिरसपत', 'सुकरवार', 'सनिवार'],
- 'weekdays_short' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'],
- 'weekdays_min' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['बिहिनियाँ', 'मंझनियाँ'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - Tim Fish
- * - shaishavgandhi05
- * - Serhan Apaydın
- * - JD Isaacks
- * - tomhorvat
- * - Josh Soref
- * - François B
- * - shaishavgandhi05
- * - Serhan Apaydın
- * - JD Isaacks
- * - tomhorvat
- * - Stjepan
- */
-return [
- 'year' => ':count godinu|:count godine|:count godina',
- 'y' => ':count god.|:count god.|:count god.',
- 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
- 'm' => ':count mj.|:count mj.|:count mj.',
- 'week' => ':count tjedan|:count tjedna|:count tjedana',
- 'w' => ':count tj.|:count tj.|:count tj.',
- 'day' => ':count dan|:count dana|:count dana',
- 'd' => ':count d.|:count d.|:count d.',
- 'hour' => ':count sat|:count sata|:count sati',
- 'h' => ':count sat|:count sata|:count sati',
- 'minute' => ':count minutu|:count minute|:count minuta',
- 'min' => ':count min.|:count min.|:count min.',
- 'second' => ':count sekundu|:count sekunde|:count sekundi',
- 's' => ':count sek.|:count sek.|:count sek.',
- 'ago' => 'prije :time',
- 'from_now' => 'za :time',
- 'after' => 'za :time',
- 'before' => 'prije :time',
- 'diff_yesterday' => 'jučer',
- 'diff_tomorrow' => 'sutra',
- 'diff_before_yesterday' => 'prekjučer',
- 'diff_after_tomorrow' => 'prekosutra',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[danas u] LT',
- 'nextDay' => '[sutra u] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[u] [nedjelju] [u] LT';
- case 3:
- return '[u] [srijedu] [u] LT';
- case 6:
- return '[u] [subotu] [u] LT';
- default:
- return '[u] dddd [u] LT';
- }
- },
- 'lastDay' => '[jučer u] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- case 3:
- return '[prošlu] dddd [u] LT';
- case 6:
- return '[prošle] [subote] [u] LT';
- default:
- return '[prošli] dddd [u] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
- 'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
- 'months_short' => ['sij.', 'velj.', 'ožu.', 'tra.', 'svi.', 'lip.', 'srp.', 'kol.', 'ruj.', 'lis.', 'stu.', 'pro.'],
- 'months_regexp' => '/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => ['nedjelju', 'ponedjeljak', 'utorak', 'srijedu', 'četvrtak', 'petak', 'subotu'],
- 'weekdays_standalone' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
- 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
- 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' i '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
- 'weekdays_short' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
- 'weekdays_min' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
- 'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
- 'months_short' => ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj', 'lis', 'stu', 'pro'],
- 'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D. M. yy.',
- 'LL' => 'D. MMM YYYY.',
- 'LLL' => 'D. MMMM YYYY. HH:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY. HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/hr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/hsb_DE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Information from Michael Wolf Andrzej Krzysztofowicz ankry@mif.pg.gda.pl
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'DD. MMMM YYYY',
- 'LLL' => 'DD. MMMM, HH:mm [hodź.]',
- 'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [hodź.]',
- ],
- 'months' => ['januara', 'februara', 'měrca', 'apryla', 'meje', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
- 'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Mej', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'],
- 'weekdays' => ['Njedźela', 'Póndźela', 'Wutora', 'Srjeda', 'Štvórtk', 'Pjatk', 'Sobota'],
- 'weekdays_short' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'],
- 'weekdays_min' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count lěto',
- 'y' => ':count lěto',
- 'a_year' => ':count lěto',
-
- 'month' => ':count měsac',
- 'm' => ':count měsac',
- 'a_month' => ':count měsac',
-
- 'week' => ':count tydźeń',
- 'w' => ':count tydźeń',
- 'a_week' => ':count tydźeń',
-
- 'day' => ':count dźeń',
- 'd' => ':count dźeń',
- 'a_day' => ':count dźeń',
-
- 'hour' => ':count hodźina',
- 'h' => ':count hodźina',
- 'a_hour' => ':count hodźina',
-
- 'minute' => ':count chwila',
- 'min' => ':count chwila',
- 'a_minute' => ':count chwila',
-
- 'second' => ':count druhi',
- 's' => ':count druhi',
- 'a_second' => ':count druhi',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ht_HT.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['janvye', 'fevriye', 'mas', 'avril', 'me', 'jen', 'jiyè', 'out', 'septanm', 'oktòb', 'novanm', 'desanm'],
- 'months_short' => ['jan', 'fev', 'mas', 'avr', 'me', 'jen', 'jiy', 'out', 'sep', 'okt', 'nov', 'des'],
- 'weekdays' => ['dimanch', 'lendi', 'madi', 'mèkredi', 'jedi', 'vandredi', 'samdi'],
- 'weekdays_short' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'],
- 'weekdays_min' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count lane',
- 'y' => ':count lane',
- 'a_year' => ':count lane',
-
- 'month' => 'mwa :count',
- 'm' => 'mwa :count',
- 'a_month' => 'mwa :count',
-
- 'week' => 'semèn :count',
- 'w' => 'semèn :count',
- 'a_week' => 'semèn :count',
-
- 'day' => ':count jou',
- 'd' => ':count jou',
- 'a_day' => ':count jou',
-
- 'hour' => ':count lè',
- 'h' => ':count lè',
- 'a_hour' => ':count lè',
-
- 'minute' => ':count minit',
- 'min' => ':count minit',
- 'a_minute' => ':count minit',
-
- 'second' => ':count segonn',
- 's' => ':count segonn',
- 'a_second' => ':count segonn',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Adam Brunner
- * - Brett Johnson
- * - balping
- */
-$huWeekEndings = ['vasárnap', 'hétfőn', 'kedden', 'szerdán', 'csütörtökön', 'pénteken', 'szombaton'];
-
-return [
- 'year' => ':count év',
- 'y' => ':count év',
- 'month' => ':count hónap',
- 'm' => ':count hónap',
- 'week' => ':count hét',
- 'w' => ':count hét',
- 'day' => ':count nap',
- 'd' => ':count nap',
- 'hour' => ':count óra',
- 'h' => ':count óra',
- 'minute' => ':count perc',
- 'min' => ':count perc',
- 'second' => ':count másodperc',
- 's' => ':count másodperc',
- 'ago' => ':time',
- 'from_now' => ':time múlva',
- 'after' => ':time később',
- 'before' => ':time korábban',
- 'year_ago' => ':count éve',
- 'month_ago' => ':count hónapja',
- 'week_ago' => ':count hete',
- 'day_ago' => ':count napja',
- 'hour_ago' => ':count órája',
- 'minute_ago' => ':count perce',
- 'second_ago' => ':count másodperce',
- 'year_after' => ':count évvel',
- 'month_after' => ':count hónappal',
- 'week_after' => ':count héttel',
- 'day_after' => ':count nappal',
- 'hour_after' => ':count órával',
- 'minute_after' => ':count perccel',
- 'second_after' => ':count másodperccel',
- 'year_before' => ':count évvel',
- 'month_before' => ':count hónappal',
- 'week_before' => ':count héttel',
- 'day_before' => ':count nappal',
- 'hour_before' => ':count órával',
- 'minute_before' => ':count perccel',
- 'second_before' => ':count másodperccel',
- 'months' => ['január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],
- 'months_short' => ['jan.', 'feb.', 'márc.', 'ápr.', 'máj.', 'jún.', 'júl.', 'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
- 'weekdays' => ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'],
- 'weekdays_short' => ['vas', 'hét', 'kedd', 'sze', 'csüt', 'pén', 'szo'],
- 'weekdays_min' => ['v', 'h', 'k', 'sze', 'cs', 'p', 'sz'],
- 'ordinal' => ':number.',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'YYYY.MM.DD.',
- 'LL' => 'YYYY. MMMM D.',
- 'LLL' => 'YYYY. MMMM D. H:mm',
- 'LLLL' => 'YYYY. MMMM D., dddd H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[ma] LT[-kor]',
- 'nextDay' => '[holnap] LT[-kor]',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) use ($huWeekEndings) {
- return '['.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]';
- },
- 'lastDay' => '[tegnap] LT[-kor]',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) use ($huWeekEndings) {
- return '[múlt '.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]';
- },
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['DE', 'DU'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' és '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/hu.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - mhamlet
- */
-return [
- 'year' => ':count տարի',
- 'a_year' => 'տարի|:count տարի',
- 'y' => ':countտ',
- 'month' => ':count ամիս',
- 'a_month' => 'ամիս|:count ամիս',
- 'm' => ':countամ',
- 'week' => ':count շաբաթ',
- 'a_week' => 'շաբաթ|:count շաբաթ',
- 'w' => ':countշ',
- 'day' => ':count օր',
- 'a_day' => 'օր|:count օր',
- 'd' => ':countօր',
- 'hour' => ':count ժամ',
- 'a_hour' => 'ժամ|:count ժամ',
- 'h' => ':countժ',
- 'minute' => ':count րոպե',
- 'a_minute' => 'րոպե|:count րոպե',
- 'min' => ':countր',
- 'second' => ':count վայրկյան',
- 'a_second' => 'մի քանի վայրկյան|:count վայրկյան',
- 's' => ':countվրկ',
- 'ago' => ':time առաջ',
- 'from_now' => ':time ներկա պահից',
- 'after' => ':time հետո',
- 'before' => ':time առաջ',
- 'diff_yesterday' => 'երեկ',
- 'diff_tomorrow' => 'վաղը',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY թ.',
- 'LLL' => 'D MMMM YYYY թ., HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY թ., HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[այսօր] LT',
- 'nextDay' => '[վաղը] LT',
- 'nextWeek' => 'dddd [օրը ժամը] LT',
- 'lastDay' => '[երեկ] LT',
- 'lastWeek' => '[անցած] dddd [օրը ժամը] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'DDD':
- case 'w':
- case 'W':
- case 'DDDo':
- return $number.($number === 1 ? '-ին' : '-րդ');
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'գիշերվա';
- }
- if ($hour < 12) {
- return 'առավոտվա';
- }
- if ($hour < 17) {
- return 'ցերեկվա';
- }
-
- return 'երեկոյան';
- },
- 'months' => ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի', 'մայիսի', 'հունիսի', 'հուլիսի', 'օգոստոսի', 'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի', 'դեկտեմբերի'],
- 'months_standalone' => ['հունվար', 'փետրվար', 'մարտ', 'ապրիլ', 'մայիս', 'հունիս', 'հուլիս', 'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր', 'նոյեմբեր', 'դեկտեմբեր'],
- 'months_short' => ['հնվ', 'փտր', 'մրտ', 'ապր', 'մյս', 'հնս', 'հլս', 'օգս', 'սպտ', 'հկտ', 'նմբ', 'դկտ'],
- 'months_regexp' => '/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => ['կիրակի', 'երկուշաբթի', 'երեքշաբթի', 'չորեքշաբթի', 'հինգշաբթի', 'ուրբաթ', 'շաբաթ'],
- 'weekdays_short' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'],
- 'weekdays_min' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'],
- 'list' => [', ', ' եւ '],
- 'first_day_of_week' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - Tim Fish
- * - Serhan Apaydın
- * - JD Isaacks
- */
-return array_replace_recursive(require __DIR__.'/hy.php', [
- 'from_now' => ':time հետո',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
- 'months' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
- 'months_short' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
- 'weekdays' => ['1', '2', '3', '4', '5', '6', '7'],
- 'weekdays_short' => ['1', '2', '3', '4', '5', '6', '7'],
- 'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ia_FR.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Fedora Project Nik Kalach nikka@fedoraproject.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['januario', 'februario', 'martio', 'april', 'maio', 'junio', 'julio', 'augusto', 'septembre', 'octobre', 'novembre', 'decembre'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
- 'weekdays' => ['dominica', 'lunedi', 'martedi', 'mercuridi', 'jovedi', 'venerdi', 'sabbato'],
- 'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
- 'weekdays_min' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => 'anno :count',
- 'y' => 'anno :count',
- 'a_year' => 'anno :count',
-
- 'month' => ':count mense',
- 'm' => ':count mense',
- 'a_month' => ':count mense',
-
- 'week' => ':count septimana',
- 'w' => ':count septimana',
- 'a_week' => ':count septimana',
-
- 'day' => ':count die',
- 'd' => ':count die',
- 'a_day' => ':count die',
-
- 'hour' => ':count hora',
- 'h' => ':count hora',
- 'a_hour' => ':count hora',
-
- 'minute' => ':count minuscule',
- 'min' => ':count minuscule',
- 'a_minute' => ':count minuscule',
-
- 'second' => ':count secunda',
- 's' => ':count secunda',
- 'a_second' => ':count secunda',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - du
- * - JD Isaacks
- * - Nafies Luthfi
- * - Raymundus Jati Primanda (mundusjp)
- */
-return [
- 'year' => ':count tahun',
- 'a_year' => '{1}setahun|]1,Inf[:count tahun',
- 'y' => ':countthn',
- 'month' => ':count bulan',
- 'a_month' => '{1}sebulan|]1,Inf[:count bulan',
- 'm' => ':countbln',
- 'week' => ':count minggu',
- 'a_week' => '{1}seminggu|]1,Inf[:count minggu',
- 'w' => ':countmgg',
- 'day' => ':count hari',
- 'a_day' => '{1}sehari|]1,Inf[:count hari',
- 'd' => ':counthr',
- 'hour' => ':count jam',
- 'a_hour' => '{1}sejam|]1,Inf[:count jam',
- 'h' => ':countj',
- 'minute' => ':count menit',
- 'a_minute' => '{1}semenit|]1,Inf[:count menit',
- 'min' => ':countmnt',
- 'second' => ':count detik',
- 'a_second' => '{1}beberapa detik|]1,Inf[:count detik',
- 's' => ':countdt',
- 'ago' => ':time yang lalu',
- 'from_now' => 'dalam :time',
- 'after' => ':time setelahnya',
- 'before' => ':time sebelumnya',
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm.ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY [pukul] HH.mm',
- 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Hari ini pukul] LT',
- 'nextDay' => '[Besok pukul] LT',
- 'nextWeek' => 'dddd [pukul] LT',
- 'lastDay' => '[Kemarin pukul] LT',
- 'lastWeek' => 'dddd [lalu pukul] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 11) {
- return 'pagi';
- }
- if ($hour < 15) {
- return 'siang';
- }
- if ($hour < 19) {
- return 'sore';
- }
-
- return 'malam';
- },
- 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
- 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
- 'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' dan '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/id.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ig_NG.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - pablo@mandriva.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Jenụwarị', 'Febrụwarị', 'Maachị', 'Eprel', 'Mee', 'Juun', 'Julaị', 'Ọgọọst', 'Septemba', 'Ọktoba', 'Novemba', 'Disemba'],
- 'months_short' => ['Jen', 'Feb', 'Maa', 'Epr', 'Mee', 'Juu', 'Jul', 'Ọgọ', 'Sep', 'Ọkt', 'Nov', 'Dis'],
- 'weekdays' => ['sọnde', 'mọnde', 'tuzde', 'wenzde', 'tọsde', 'fraịde', 'satọde'],
- 'weekdays_short' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'],
- 'weekdays_min' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => 'afo :count',
- 'y' => 'afo :count',
- 'a_year' => 'afo :count',
-
- 'month' => 'önwa :count',
- 'm' => 'önwa :count',
- 'a_month' => 'önwa :count',
-
- 'week' => 'izu :count',
- 'w' => 'izu :count',
- 'a_week' => 'izu :count',
-
- 'day' => 'ụbọchị :count',
- 'd' => 'ụbọchị :count',
- 'a_day' => 'ụbọchị :count',
-
- 'hour' => 'awa :count',
- 'h' => 'awa :count',
- 'a_hour' => 'awa :count',
-
- 'minute' => 'minit :count',
- 'min' => 'minit :count',
- 'a_minute' => 'minit :count',
-
- 'second' => 'sekọnd :count',
- 's' => 'sekọnd :count',
- 'a_second' => 'sekọnd :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['ꎸꄑ', 'ꁯꋒ'],
- 'weekdays' => ['ꑭꆏꑍ', 'ꆏꊂꋍ', 'ꆏꊂꑍ', 'ꆏꊂꌕ', 'ꆏꊂꇖ', 'ꆏꊂꉬ', 'ꆏꊂꃘ'],
- 'weekdays_short' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'],
- 'weekdays_min' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'],
- 'months' => null,
- 'months_short' => ['ꋍꆪ', 'ꑍꆪ', 'ꌕꆪ', 'ꇖꆪ', 'ꉬꆪ', 'ꃘꆪ', 'ꏃꆪ', 'ꉆꆪ', 'ꈬꆪ', 'ꊰꆪ', 'ꊰꊪꆪ', 'ꊰꑋꆪ'],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D h:mm a',
- 'LLLL' => 'YYYY MMMM D, dddd h:mm a',
- ],
-
- 'year' => ':count ꒉ', // less reliable
- 'y' => ':count ꒉ', // less reliable
- 'a_year' => ':count ꒉ', // less reliable
-
- 'month' => ':count ꆪ',
- 'm' => ':count ꆪ',
- 'a_month' => ':count ꆪ',
-
- 'week' => ':count ꏃ', // less reliable
- 'w' => ':count ꏃ', // less reliable
- 'a_week' => ':count ꏃ', // less reliable
-
- 'day' => ':count ꏜ', // less reliable
- 'd' => ':count ꏜ', // less reliable
- 'a_day' => ':count ꏜ', // less reliable
-
- 'hour' => ':count ꄮꈉ',
- 'h' => ':count ꄮꈉ',
- 'a_hour' => ':count ꄮꈉ',
-
- 'minute' => ':count ꀄꊭ', // less reliable
- 'min' => ':count ꀄꊭ', // less reliable
- 'a_minute' => ':count ꀄꊭ', // less reliable
-
- 'second' => ':count ꇅ', // less reliable
- 's' => ':count ꇅ', // less reliable
- 'a_second' => ':count ꇅ', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ik_CA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - pablo@mandriva.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Siqiññaatchiaq', 'Siqiññaasrugruk', 'Paniqsiqsiivik', 'Qilġich Tatqiat', 'Suppivik', 'Iġñivik', 'Itchavik', 'Tiññivik', 'Amiġaiqsivik', 'Sikkuvik', 'Nippivik', 'Siqiñġiḷaq'],
- 'months_short' => ['Sñt', 'Sñs', 'Pan', 'Qil', 'Sup', 'Iġñ', 'Itc', 'Tiñ', 'Ami', 'Sik', 'Nip', 'Siq'],
- 'weekdays' => ['Minġuiqsioiq', 'Savałłiq', 'Ilaqtchiioiq', 'Qitchiioiq', 'Sisamiioiq', 'Tallimmiioiq', 'Maqinġuoiq'],
- 'weekdays_short' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'],
- 'weekdays_min' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count ukiuq',
- 'y' => ':count ukiuq',
- 'a_year' => ':count ukiuq',
-
- 'month' => ':count Tatqiat',
- 'm' => ':count Tatqiat',
- 'a_month' => ':count Tatqiat',
-
- 'week' => ':count tatqiat', // less reliable
- 'w' => ':count tatqiat', // less reliable
- 'a_week' => ':count tatqiat', // less reliable
-
- 'day' => ':count siqiñiq', // less reliable
- 'd' => ':count siqiñiq', // less reliable
- 'a_day' => ':count siqiñiq', // less reliable
-
- 'hour' => ':count Siḷa', // less reliable
- 'h' => ':count Siḷa', // less reliable
- 'a_hour' => ':count Siḷa', // less reliable
-
- 'second' => ':count iġñiq', // less reliable
- 's' => ':count iġñiq', // less reliable
- 'a_second' => ':count iġñiq', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
- 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
- 'weekdays_min' => ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm.ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH.mm',
- 'LLLL' => 'dddd, DD MMMM YYYY HH.mm',
- ],
-
- 'year' => 'tahun :count',
- 'y' => 'tahun :count',
- 'a_year' => 'tahun :count',
-
- 'month' => ':count bulan',
- 'm' => ':count bulan',
- 'a_month' => ':count bulan',
-
- 'week' => ':count minggu',
- 'w' => ':count minggu',
- 'a_week' => ':count minggu',
-
- 'day' => ':count hari',
- 'd' => ':count hari',
- 'a_day' => ':count hari',
-
- 'hour' => ':count jam',
- 'h' => ':count jam',
- 'a_hour' => ':count jam',
-
- 'minute' => ':count menit',
- 'min' => ':count menit',
- 'a_minute' => ':count menit',
-
- 'second' => ':count detik',
- 's' => ':count detik',
- 'a_second' => ':count detik',
-
- 'ago' => ':time yang lalu',
- 'from_now' => 'dalam :time',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kristján Ingi Geirsson
- */
-return [
- 'year' => '1 ár|:count ár',
- 'y' => '1 ár|:count ár',
- 'month' => '1 mánuður|:count mánuðir',
- 'm' => '1 mánuður|:count mánuðir',
- 'week' => '1 vika|:count vikur',
- 'w' => '1 vika|:count vikur',
- 'day' => '1 dagur|:count dagar',
- 'd' => '1 dagur|:count dagar',
- 'hour' => '1 klukkutími|:count klukkutímar',
- 'h' => '1 klukkutími|:count klukkutímar',
- 'minute' => '1 mínúta|:count mínútur',
- 'min' => '1 mínúta|:count mínútur',
- 'second' => '1 sekúnda|:count sekúndur',
- 's' => '1 sekúnda|:count sekúndur',
- 'ago' => ':time síðan',
- 'from_now' => ':time síðan',
- 'after' => ':time eftir',
- 'before' => ':time fyrir',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' og '],
- 'meridiem' => ['fh', 'eh'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM [kl.] HH:mm',
- 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
- ],
- 'weekdays' => ['sunnudaginn', 'mánudaginn', 'þriðjudaginn', 'miðvikudaginn', 'fimmtudaginn', 'föstudaginn', 'laugardaginn'],
- 'weekdays_short' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],
- 'weekdays_min' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],
- 'months' => ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maí', 'jún', 'júl', 'ágú', 'sep', 'okt', 'nóv', 'des'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/is.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ash
- * - François B
- * - Marco Perrando
- * - Massimiliano Caniparoli
- * - JD Isaacks
- * - Andrea Martini
- * - Francesco Marasco
- * - Tizianoz93
- * - Davide Casiraghi (davide-casiraghi)
- */
-return [
- 'year' => ':count anno|:count anni',
- 'a_year' => 'un anno|:count anni',
- 'y' => ':count anno|:count anni',
- 'month' => ':count mese|:count mesi',
- 'a_month' => 'un mese|:count mesi',
- 'm' => ':count mese|:count mesi',
- 'week' => ':count settimana|:count settimane',
- 'a_week' => 'una settimana|:count settimane',
- 'w' => ':count set.',
- 'day' => ':count giorno|:count giorni',
- 'a_day' => 'un giorno|:count giorni',
- 'd' => ':count g|:count gg',
- 'hour' => ':count ora|:count ore',
- 'a_hour' => 'un\'ora|:count ore',
- 'h' => ':count h',
- 'minute' => ':count minuto|:count minuti',
- 'a_minute' => 'un minuto|:count minuti',
- 'min' => ':count min.',
- 'second' => ':count secondo|:count secondi',
- 'a_second' => 'alcuni secondi|:count secondi',
- 's' => ':count sec.',
- 'ago' => ':time fa',
- 'from_now' => function ($time) {
- return (preg_match('/^[0-9].+$/', $time) ? 'tra' : 'in')." $time";
- },
- 'after' => ':time dopo',
- 'before' => ':time prima',
- 'diff_now' => 'proprio ora',
- 'diff_yesterday' => 'ieri',
- 'diff_tomorrow' => 'domani',
- 'diff_before_yesterday' => 'l\'altro ieri',
- 'diff_after_tomorrow' => 'dopodomani',
- 'period_interval' => 'ogni :interval',
- 'period_start_date' => 'dal :date',
- 'period_end_date' => 'al :date',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Oggi alle] LT',
- 'nextDay' => '[Domani alle] LT',
- 'nextWeek' => 'dddd [alle] LT',
- 'lastDay' => '[Ieri alle] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[la scorsa] dddd [alle] LT';
- default:
- return '[lo scorso] dddd [alle] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberº',
- 'months' => ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
- 'months_short' => ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic'],
- 'weekdays' => ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato'],
- 'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
- 'weekdays_min' => ['do', 'lu', 'ma', 'me', 'gi', 've', 'sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' e '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Propaganistas
- */
-return array_replace_recursive(require __DIR__.'/it.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return require __DIR__.'/it.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/it.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/it.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/iu_CA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Pablo Saratxaga pablo@mandriva.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'MM/DD/YY',
- ],
- 'months' => ['ᔮᓄᐊᓕ', 'ᕕᕗᐊᓕ', 'ᒪᔅᓯ', 'ᐃᐳᓗ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚᐃ', 'ᐊᒋᓯ', 'ᓯᑎᕙ', 'ᐊᑦᑐᕙ', 'ᓄᕕᕙ', 'ᑎᓯᕝᕙ'],
- 'months_short' => ['ᔮᓄ', 'ᕕᕗ', 'ᒪᔅ', 'ᐃᐳ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚ', 'ᐊᒋ', 'ᓯᑎ', 'ᐊᑦ', 'ᓄᕕ', 'ᑎᓯ'],
- 'weekdays' => ['ᓈᑦᑎᖑᔭᕐᕕᒃ', 'ᓇᒡᒐᔾᔭᐅ', 'ᓇᒡᒐᔾᔭᐅᓕᖅᑭᑦ', 'ᐱᖓᓲᓕᖅᓯᐅᑦ', 'ᕿᑎᖅᑰᑦ', 'ᐅᓪᓗᕈᓘᑐᐃᓇᖅ', 'ᓯᕙᑖᕕᒃ'],
- 'weekdays_short' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'],
- 'weekdays_min' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count ᐅᑭᐅᖅ',
- 'y' => ':count ᐅᑭᐅᖅ',
- 'a_year' => ':count ᐅᑭᐅᖅ',
-
- 'month' => ':count qaammat',
- 'm' => ':count qaammat',
- 'a_month' => ':count qaammat',
-
- 'week' => ':count sapaatip akunnera',
- 'w' => ':count sapaatip akunnera',
- 'a_week' => ':count sapaatip akunnera',
-
- 'day' => ':count ulloq',
- 'd' => ':count ulloq',
- 'a_day' => ':count ulloq',
-
- 'hour' => ':count ikarraq',
- 'h' => ':count ikarraq',
- 'a_hour' => ':count ikarraq',
-
- 'minute' => ':count titiqqaralaaq', // less reliable
- 'min' => ':count titiqqaralaaq', // less reliable
- 'a_minute' => ':count titiqqaralaaq', // less reliable
-
- 'second' => ':count marluk', // less reliable
- 's' => ':count marluk', // less reliable
- 'a_second' => ':count marluk', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],
- 'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],
- 'weekdays' => ['יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'יום שבת'],
- 'weekdays_short' => ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'],
- 'weekdays_min' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
- 'meridiem' => ['לפנה״צ', 'אחה״צ'],
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'D.M.YYYY',
- 'LL' => 'D בMMM YYYY',
- 'LLL' => 'D בMMMM YYYY H:mm',
- 'LLLL' => 'dddd, D בMMMM YYYY H:mm',
- ],
-
- 'year' => ':count שנה',
- 'y' => ':count שנה',
- 'a_year' => ':count שנה',
-
- 'month' => ':count חודש',
- 'm' => ':count חודש',
- 'a_month' => ':count חודש',
-
- 'week' => ':count שבוע',
- 'w' => ':count שבוע',
- 'a_week' => ':count שבוע',
-
- 'day' => ':count יום',
- 'd' => ':count יום',
- 'a_day' => ':count יום',
-
- 'hour' => ':count שעה',
- 'h' => ':count שעה',
- 'a_hour' => ':count שעה',
-
- 'minute' => ':count דקה',
- 'min' => ':count דקה',
- 'a_minute' => ':count דקה',
-
- 'second' => ':count שניה',
- 's' => ':count שניה',
- 'a_second' => ':count שניה',
-
- 'ago' => 'לפני :time',
- 'from_now' => 'בעוד :time',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Takuya Sawada
- * - Atsushi Tanaka
- * - François B
- * - Jason Katz-Brown
- * - Serhan Apaydın
- * - XueWei
- * - JD Isaacks
- * - toyama satoshi
- * - atakigawa
- */
-return [
- 'year' => ':count年',
- 'y' => ':count年',
- 'month' => ':countヶ月',
- 'm' => ':countヶ月',
- 'week' => ':count週間',
- 'w' => ':count週間',
- 'day' => ':count日',
- 'd' => ':count日',
- 'hour' => ':count時間',
- 'h' => ':count時間',
- 'minute' => ':count分',
- 'min' => ':count分',
- 'second' => ':count秒',
- 'a_second' => '{1}数秒|]1,Inf[:count秒',
- 's' => ':count秒',
- 'ago' => ':time前',
- 'from_now' => ':time後',
- 'after' => ':time後',
- 'before' => ':time前',
- 'diff_yesterday' => '昨日',
- 'diff_tomorrow' => '明日',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY年M月D日',
- 'LLL' => 'YYYY年M月D日 HH:mm',
- 'LLLL' => 'YYYY年M月D日 dddd HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[今日] LT',
- 'nextDay' => '[明日] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
- if ($other->week !== $current->week) {
- return '[来週]dddd LT';
- }
-
- return 'dddd LT';
- },
- 'lastDay' => '[昨日] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
- if ($other->week !== $current->week) {
- return '[先週]dddd LT';
- }
-
- return 'dddd LT';
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'日';
- default:
- return $number;
- }
- },
- 'meridiem' => ['午前', '午後'],
- 'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
- 'weekdays_short' => ['日', '月', '火', '水', '木', '金', '土'],
- 'weekdays_min' => ['日', '月', '火', '水', '木', '金', '土'],
- 'list' => '、',
- 'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九'],
- 'alt_numbers_pow' => [
- 10000 => '万',
- 1000 => '千',
- 100 => '百',
- ],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ja.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['utuko', 'kyiukonyi'],
- 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - tgfjt
- * - JD Isaacks
- */
-return [
- 'year' => '{1}setaun|]1,Inf[:count taun',
- 'month' => '{1}sewulan|]1,Inf[:count wulan',
- 'week' => '{1}sakminggu|]1,Inf[:count minggu',
- 'day' => '{1}sedinten|]1,Inf[:count dinten',
- 'hour' => '{1}setunggal jam|]1,Inf[:count jam',
- 'minute' => '{1}setunggal menit|]1,Inf[:count menit',
- 'second' => '{1}sawetawis detik|]1,Inf[:count detik',
- 'ago' => ':time ingkang kepengker',
- 'from_now' => 'wonten ing :time',
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm.ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY [pukul] HH.mm',
- 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Dinten puniko pukul] LT',
- 'nextDay' => '[Mbenjang pukul] LT',
- 'nextWeek' => 'dddd [pukul] LT',
- 'lastDay' => '[Kala wingi pukul] LT',
- 'lastWeek' => 'dddd [kepengker pukul] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 11) {
- return 'enjing';
- }
- if ($hour < 15) {
- return 'siyang';
- }
- if ($hour < 19) {
- return 'sonten';
- }
-
- return 'ndalu';
- },
- 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'Nopember', 'Desember'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nop', 'Des'],
- 'weekdays' => ['Minggu', 'Senen', 'Seloso', 'Rebu', 'Kemis', 'Jemuwah', 'Septu'],
- 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Reb', 'Kem', 'Jem', 'Sep'],
- 'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sp'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' lan '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Tornike Razmadze
- * - François B
- * - Lasha Dolidze
- * - Tim Fish
- * - JD Isaacks
- * - Tornike Razmadze
- * - François B
- * - Lasha Dolidze
- * - JD Isaacks
- * - LONGMAN
- * - Avtandil Kikabidze (akalongman)
- */
-return [
- 'year' => ':count წელი',
- 'y' => ':count წელი',
- 'a_year' => '{1}წელი|]1,Inf[:count წელი',
- 'month' => ':count თვე',
- 'm' => ':count თვე',
- 'a_month' => '{1}თვე|]1,Inf[:count თვე',
- 'week' => ':count კვირა',
- 'w' => ':count კვირა',
- 'a_week' => '{1}კვირა|]1,Inf[:count კვირა',
- 'day' => ':count დღე',
- 'd' => ':count დღე',
- 'a_day' => '{1}დღე|]1,Inf[:count დღე',
- 'hour' => ':count საათი',
- 'h' => ':count საათი',
- 'a_hour' => '{1}საათი|]1,Inf[:count საათი',
- 'minute' => ':count წუთი',
- 'min' => ':count წუთი',
- 'a_minute' => '{1}წუთი|]1,Inf[:count წუთი',
- 'second' => ':count წამი',
- 's' => ':count წამი',
- 'a_second' => '{1}რამდენიმე წამი|]1,Inf[:count წამი',
- 'ago' => function ($time) {
- $replacements = [
- // year
- 'წელი' => 'წლის',
- // month
- 'თვე' => 'თვის',
- // week
- 'კვირა' => 'კვირის',
- // day
- 'დღე' => 'დღის',
- // hour
- 'საათი' => 'საათის',
- // minute
- 'წუთი' => 'წუთის',
- // second
- 'წამი' => 'წამის',
- ];
- $time = strtr($time, array_flip($replacements));
- $time = strtr($time, $replacements);
-
- return "$time წინ";
- },
- 'from_now' => function ($time) {
- $replacements = [
- // year
- 'წელი' => 'წელიწადში',
- // week
- 'კვირა' => 'კვირაში',
- // day
- 'დღე' => 'დღეში',
- // month
- 'თვე' => 'თვეში',
- // hour
- 'საათი' => 'საათში',
- // minute
- 'წუთი' => 'წუთში',
- // second
- 'წამი' => 'წამში',
- ];
- $time = strtr($time, array_flip($replacements));
- $time = strtr($time, $replacements);
-
- return $time;
- },
- 'after' => function ($time) {
- $replacements = [
- // year
- 'წელი' => 'წლის',
- // month
- 'თვე' => 'თვის',
- // week
- 'კვირა' => 'კვირის',
- // day
- 'დღე' => 'დღის',
- // hour
- 'საათი' => 'საათის',
- // minute
- 'წუთი' => 'წუთის',
- // second
- 'წამი' => 'წამის',
- ];
- $time = strtr($time, array_flip($replacements));
- $time = strtr($time, $replacements);
-
- return "$time შემდეგ";
- },
- 'before' => function ($time) {
- $replacements = [
- // year
- 'წელი' => 'წლის',
- // month
- 'თვე' => 'თვის',
- // week
- 'კვირი' => 'კვირის',
- // day
- 'დღე' => 'დღის',
- // hour
- 'საათი' => 'საათის',
- // minute
- 'წუთი' => 'წუთის',
- // second
- 'წამი' => 'წამის',
- ];
- $time = strtr($time, array_flip($replacements));
- $time = strtr($time, $replacements);
-
- return "$time უკან";
- },
- 'diff_yesterday' => 'გუშინ',
- 'diff_tomorrow' => 'ხვალ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[დღეს], LT[-ზე]',
- 'nextDay' => '[ხვალ], LT[-ზე]',
- 'nextWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
- return ($current->isSameWeek($other) ? '' : '[შემდეგ] ').'dddd, LT[-ზე]';
- },
- 'lastDay' => '[გუშინ], LT[-ზე]',
- 'lastWeek' => '[წინა] dddd, LT-ზე',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- if ($number === 0) {
- return $number;
- }
- if ($number === 1) {
- return $number.'-ლი';
- }
- if (($number < 20) || ($number <= 100 && ($number % 20 === 0)) || ($number % 100 === 0)) {
- return 'მე-'.$number;
- }
-
- return $number.'-ე';
- },
- 'months' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილის', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
- 'months_standalone' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
- 'months_short' => ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'],
- 'months_regexp' => '/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => ['კვირას', 'ორშაბათს', 'სამშაბათს', 'ოთხშაბათს', 'ხუთშაბათს', 'პარასკევს', 'შაბათს'],
- 'weekdays_standalone' => ['კვირა', 'ორშაბათი', 'სამშაბათი', 'ოთხშაბათი', 'ხუთშაბათი', 'პარასკევი', 'შაბათი'],
- 'weekdays_short' => ['კვი', 'ორშ', 'სამ', 'ოთხ', 'ხუთ', 'პარ', 'შაბ'],
- 'weekdays_min' => ['კვ', 'ორ', 'სა', 'ოთ', 'ხუ', 'პა', 'შა'],
- 'weekdays_regexp' => '/^([^d].*|.*[^d])$/',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' და '],
- 'meridiem' => function ($hour) {
- if ($hour >= 4) {
- if ($hour < 11) {
- return 'დილის';
- }
-
- if ($hour < 16) {
- return 'შუადღის';
- }
-
- if ($hour < 22) {
- return 'საღამოს';
- }
- }
-
- return 'ღამის';
- },
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ka.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/kab_DZ.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - belkacem77@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Yennayer', 'Fuṛar', 'Meɣres', 'Yebrir', 'Mayyu', 'Yunyu', 'Yulyu', 'ɣuct', 'Ctembeṛ', 'Tubeṛ', 'Wambeṛ', 'Dujembeṛ'],
- 'months_short' => ['Yen', 'Fur', 'Meɣ', 'Yeb', 'May', 'Yun', 'Yul', 'ɣuc', 'Cte', 'Tub', 'Wam', 'Duj'],
- 'weekdays' => ['Acer', 'Arim', 'Aram', 'Ahad', 'Amhad', 'Sem', 'Sed'],
- 'weekdays_short' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'],
- 'weekdays_min' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['FT', 'MD'],
-
- 'year' => ':count n yiseggasen',
- 'y' => ':count n yiseggasen',
- 'a_year' => ':count n yiseggasen',
-
- 'month' => ':count n wayyuren',
- 'm' => ':count n wayyuren',
- 'a_month' => ':count n wayyuren',
-
- 'week' => ':count n ledwaṛ', // less reliable
- 'w' => ':count n ledwaṛ', // less reliable
- 'a_week' => ':count n ledwaṛ', // less reliable
-
- 'day' => ':count n wussan',
- 'd' => ':count n wussan',
- 'a_day' => ':count n wussan',
-
- 'hour' => ':count n tsaɛtin',
- 'h' => ':count n tsaɛtin',
- 'a_hour' => ':count n tsaɛtin',
-
- 'minute' => ':count n tedqiqin',
- 'min' => ':count n tedqiqin',
- 'a_minute' => ':count n tedqiqin',
-
- 'second' => ':count tasdidt', // less reliable
- 's' => ':count tasdidt', // less reliable
- 'a_second' => ':count tasdidt', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Ĩyakwakya', 'Ĩyawĩoo'],
- 'weekdays' => ['Wa kyumwa', 'Wa kwambĩlĩlya', 'Wa kelĩ', 'Wa katatũ', 'Wa kana', 'Wa katano', 'Wa thanthatũ'],
- 'weekdays_short' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
- 'weekdays_min' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
- 'months' => ['Mwai wa mbee', 'Mwai wa kelĩ', 'Mwai wa katatũ', 'Mwai wa kana', 'Mwai wa katano', 'Mwai wa thanthatũ', 'Mwai wa muonza', 'Mwai wa nyaanya', 'Mwai wa kenda', 'Mwai wa ĩkumi', 'Mwai wa ĩkumi na ĩmwe', 'Mwai wa ĩkumi na ilĩ'],
- 'months_short' => ['Mbe', 'Kel', 'Ktũ', 'Kan', 'Ktn', 'Tha', 'Moo', 'Nya', 'Knd', 'Ĩku', 'Ĩkm', 'Ĩkl'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- // Too unreliable
- /*
- 'year' => ':count mbua', // less reliable
- 'y' => ':count mbua', // less reliable
- 'a_year' => ':count mbua', // less reliable
-
- 'month' => ':count ndakitali', // less reliable
- 'm' => ':count ndakitali', // less reliable
- 'a_month' => ':count ndakitali', // less reliable
-
- 'day' => ':count wia', // less reliable
- 'd' => ':count wia', // less reliable
- 'a_day' => ':count wia', // less reliable
-
- 'hour' => ':count orasan', // less reliable
- 'h' => ':count orasan', // less reliable
- 'a_hour' => ':count orasan', // less reliable
-
- 'minute' => ':count orasan', // less reliable
- 'min' => ':count orasan', // less reliable
- 'a_minute' => ':count orasan', // less reliable
- */
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Muhi', 'Chilo'],
- 'weekdays' => ['Liduva lyapili', 'Liduva lyatatu', 'Liduva lyanchechi', 'Liduva lyannyano', 'Liduva lyannyano na linji', 'Liduva lyannyano na mavili', 'Liduva litandi'],
- 'weekdays_short' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
- 'weekdays_min' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
- 'months' => ['Mwedi Ntandi', 'Mwedi wa Pili', 'Mwedi wa Tatu', 'Mwedi wa Nchechi', 'Mwedi wa Nnyano', 'Mwedi wa Nnyano na Umo', 'Mwedi wa Nnyano na Mivili', 'Mwedi wa Nnyano na Mitatu', 'Mwedi wa Nnyano na Nchechi', 'Mwedi wa Nnyano na Nnyano', 'Mwedi wa Nnyano na Nnyano na U', 'Mwedi wa Nnyano na Nnyano na M'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['a', 'p'],
- 'weekdays' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sabadu'],
- 'weekdays_short' => ['dum', 'sig', 'ter', 'kua', 'kin', 'ses', 'sab'],
- 'weekdays_min' => ['du', 'si', 'te', 'ku', 'ki', 'se', 'sa'],
- 'weekdays_standalone' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sábadu'],
- 'months' => ['Janeru', 'Febreru', 'Marsu', 'Abril', 'Maiu', 'Junhu', 'Julhu', 'Agostu', 'Setenbru', 'Otubru', 'Nuvenbru', 'Dizenbru'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Otu', 'Nuv', 'Diz'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D [di] MMMM [di] YYYY HH:mm',
- 'LLLL' => 'dddd, D [di] MMMM [di] YYYY HH:mm',
- ],
-
- 'year' => ':count otunu', // less reliable
- 'y' => ':count otunu', // less reliable
- 'a_year' => ':count otunu', // less reliable
-
- 'week' => ':count día dumingu', // less reliable
- 'w' => ':count día dumingu', // less reliable
- 'a_week' => ':count día dumingu', // less reliable
-
- 'day' => ':count diâ', // less reliable
- 'd' => ':count diâ', // less reliable
- 'a_day' => ':count diâ', // less reliable
-
- 'minute' => ':count sugundu', // less reliable
- 'min' => ':count sugundu', // less reliable
- 'a_minute' => ':count sugundu', // less reliable
-
- 'second' => ':count dós', // less reliable
- 's' => ':count dós', // less reliable
- 'a_second' => ':count dós', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Adduha', 'Aluula'],
- 'weekdays' => ['Alhadi', 'Atini', 'Atalata', 'Alarba', 'Alhamiisa', 'Aljuma', 'Assabdu'],
- 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
- 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
- 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
- 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Kiroko', 'Hwaĩ-inĩ'],
- 'weekdays' => ['Kiumia', 'Njumatatũ', 'Njumaine', 'Njumatana', 'Aramithi', 'Njumaa', 'Njumamothi'],
- 'weekdays_short' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
- 'weekdays_min' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
- 'months' => ['Njenuarĩ', 'Mwere wa kerĩ', 'Mwere wa gatatũ', 'Mwere wa kana', 'Mwere wa gatano', 'Mwere wa gatandatũ', 'Mwere wa mũgwanja', 'Mwere wa kanana', 'Mwere wa kenda', 'Mwere wa ikũmi', 'Mwere wa ikũmi na ũmwe', 'Ndithemba'],
- 'months_short' => ['JEN', 'WKR', 'WGT', 'WKN', 'WTN', 'WTD', 'WMJ', 'WNN', 'WKD', 'WIK', 'WMW', 'DIT'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count mĩaka', // less reliable
- 'y' => ':count mĩaka', // less reliable
- 'a_year' => ':count mĩaka', // less reliable
-
- 'month' => ':count mweri', // less reliable
- 'm' => ':count mweri', // less reliable
- 'a_month' => ':count mweri', // less reliable
-
- 'week' => ':count kiumia', // less reliable
- 'w' => ':count kiumia', // less reliable
- 'a_week' => ':count kiumia', // less reliable
-
- 'day' => ':count mũthenya', // less reliable
- 'd' => ':count mũthenya', // less reliable
- 'a_day' => ':count mũthenya', // less reliable
-
- 'hour' => ':count thaa', // less reliable
- 'h' => ':count thaa', // less reliable
- 'a_hour' => ':count thaa', // less reliable
-
- 'minute' => ':count mundu', // less reliable
- 'min' => ':count mundu', // less reliable
- 'a_minute' => ':count mundu', // less reliable
-
- 'second' => ':count igego', // less reliable
- 's' => ':count igego', // less reliable
- 'a_second' => ':count igego', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'kk');
-
-/*
- * Authors:
- * - Josh Soref
- * - François B
- * - Talat Uspanov
- * - Нурлан Рахимжанов
- * - Toleugazy Kali
- */
-return [
- 'year' => ':count жыл',
- 'a_year' => 'бір жыл|:count жыл',
- 'y' => ':count ж.',
- 'month' => ':count ай',
- 'a_month' => 'бір ай|:count ай',
- 'm' => ':count ай',
- 'week' => ':count апта',
- 'a_week' => 'бір апта',
- 'w' => ':count ап.',
- 'day' => ':count күн',
- 'a_day' => 'бір күн|:count күн',
- 'd' => ':count к.',
- 'hour' => ':count сағат',
- 'a_hour' => 'бір сағат|:count сағат',
- 'h' => ':count са.',
- 'minute' => ':count минут',
- 'a_minute' => 'бір минут|:count минут',
- 'min' => ':count м.',
- 'second' => ':count секунд',
- 'a_second' => 'бірнеше секунд|:count секунд',
- 's' => ':count се.',
- 'ago' => ':time бұрын',
- 'from_now' => ':time ішінде',
- 'after' => ':time кейін',
- 'before' => ':time бұрын',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Бүгін сағат] LT',
- 'nextDay' => '[Ертең сағат] LT',
- 'nextWeek' => 'dddd [сағат] LT',
- 'lastDay' => '[Кеше сағат] LT',
- 'lastWeek' => '[Өткен аптаның] dddd [сағат] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- static $suffixes = [
- 0 => '-ші',
- 1 => '-ші',
- 2 => '-ші',
- 3 => '-ші',
- 4 => '-ші',
- 5 => '-ші',
- 6 => '-шы',
- 7 => '-ші',
- 8 => '-ші',
- 9 => '-шы',
- 10 => '-шы',
- 20 => '-шы',
- 30 => '-шы',
- 40 => '-шы',
- 50 => '-ші',
- 60 => '-шы',
- 70 => '-ші',
- 80 => '-ші',
- 90 => '-шы',
- 100 => '-ші',
- ];
-
- return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
- },
- 'months' => ['қаңтар', 'ақпан', 'наурыз', 'сәуір', 'мамыр', 'маусым', 'шілде', 'тамыз', 'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
- 'months_short' => ['қаң', 'ақп', 'нау', 'сәу', 'мам', 'мау', 'шіл', 'там', 'қыр', 'қаз', 'қар', 'жел'],
- 'weekdays' => ['жексенбі', 'дүйсенбі', 'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'],
- 'weekdays_short' => ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұм', 'сен'],
- 'weekdays_min' => ['жк', 'дй', 'сй', 'ср', 'бй', 'жм', 'сн'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' және '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/kk.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/kl_GL.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Danish Standards Association bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'MMM DD YYYY',
- ],
- 'months' => ['januaarip', 'februaarip', 'marsip', 'apriilip', 'maajip', 'juunip', 'juulip', 'aggustip', 'septembarip', 'oktobarip', 'novembarip', 'decembarip'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'weekdays' => ['sapaat', 'ataasinngorneq', 'marlunngorneq', 'pingasunngorneq', 'sisamanngorneq', 'tallimanngorneq', 'arfininngorneq'],
- 'weekdays_short' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
- 'weekdays_min' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count ukioq', // less reliable
- 'y' => ':count ukioq', // less reliable
- 'a_year' => ':count ukioq', // less reliable
-
- 'month' => ':count Ukiup qaammatai',
- 'm' => ':count Ukiup qaammatai',
- 'a_month' => ':count Ukiup qaammatai',
-
- 'week' => ':count sapaat', // less reliable
- 'w' => ':count sapaat', // less reliable
- 'a_week' => ':count sapaat', // less reliable
-
- 'day' => ':count ulloq',
- 'd' => ':count ulloq',
- 'a_day' => ':count ulloq',
-
- 'hour' => ':count akunneq',
- 'h' => ':count akunneq',
- 'a_hour' => ':count akunneq',
-
- 'minute' => ':count eqqumiitsuliorneq', // less reliable
- 'min' => ':count eqqumiitsuliorneq', // less reliable
- 'a_minute' => ':count eqqumiitsuliorneq', // less reliable
-
- 'second' => ':count marluk', // less reliable
- 's' => ':count marluk', // less reliable
- 'a_second' => ':count marluk', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['krn', 'koosk'],
- 'weekdays' => ['Kotisap', 'Kotaai', 'Koaeng’', 'Kosomok', 'Koang’wan', 'Komuut', 'Kolo'],
- 'weekdays_short' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'],
- 'weekdays_min' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'],
- 'months' => ['Mulgul', 'Ng’atyaato', 'Kiptaamo', 'Iwootkuut', 'Mamuut', 'Paagi', 'Ng’eiyeet', 'Rooptui', 'Bureet', 'Epeeso', 'Kipsuunde ne taai', 'Kipsuunde nebo aeng’'],
- 'months_short' => ['Mul', 'Ngat', 'Taa', 'Iwo', 'Mam', 'Paa', 'Nge', 'Roo', 'Bur', 'Epe', 'Kpt', 'Kpa'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count maghatiat', // less reliable
- 'y' => ':count maghatiat', // less reliable
- 'a_year' => ':count maghatiat', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kruy Vanna
- * - Sereysethy Touch
- * - JD Isaacks
- * - Sovichet Tep
- */
-return [
- 'year' => '{1}មួយឆ្នាំ|]1,Inf[:count ឆ្នាំ',
- 'y' => ':count ឆ្នាំ',
- 'month' => '{1}មួយខែ|]1,Inf[:count ខែ',
- 'm' => ':count ខែ',
- 'week' => ':count សប្ដាហ៍',
- 'w' => ':count សប្ដាហ៍',
- 'day' => '{1}មួយថ្ងៃ|]1,Inf[:count ថ្ងៃ',
- 'd' => ':count ថ្ងៃ',
- 'hour' => '{1}មួយម៉ោង|]1,Inf[:count ម៉ោង',
- 'h' => ':count ម៉ោង',
- 'minute' => '{1}មួយនាទី|]1,Inf[:count នាទី',
- 'min' => ':count នាទី',
- 'second' => '{1}ប៉ុន្មានវិនាទី|]1,Inf[:count វិនាទី',
- 's' => ':count វិនាទី',
- 'ago' => ':timeមុន',
- 'from_now' => ':timeទៀត',
- 'after' => 'នៅក្រោយ :time',
- 'before' => 'នៅមុន :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[ថ្ងៃនេះ ម៉ោង] LT',
- 'nextDay' => '[ស្អែក ម៉ោង] LT',
- 'nextWeek' => 'dddd [ម៉ោង] LT',
- 'lastDay' => '[ម្សិលមិញ ម៉ោង] LT',
- 'lastWeek' => 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => 'ទី:number',
- 'meridiem' => ['ព្រឹក', 'ល្ងាច'],
- 'months' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'],
- 'months_short' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'],
- 'weekdays' => ['អាទិត្យ', 'ច័ន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],
- 'weekdays_short' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'],
- 'weekdays_min' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', 'និង '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/km.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - MOHAN M U
- * - François B
- * - rajeevnaikte
- */
-return [
- 'year' => '{1}ಒಂದು ವರ್ಷ|]1,Inf[:count ವರ್ಷ',
- 'month' => '{1}ಒಂದು ತಿಂಗಳು|]1,Inf[:count ತಿಂಗಳು',
- 'week' => '{1}ಒಂದು ವಾರ|]1,Inf[:count ವಾರಗಳು',
- 'day' => '{1}ಒಂದು ದಿನ|]1,Inf[:count ದಿನ',
- 'hour' => '{1}ಒಂದು ಗಂಟೆ|]1,Inf[:count ಗಂಟೆ',
- 'minute' => '{1}ಒಂದು ನಿಮಿಷ|]1,Inf[:count ನಿಮಿಷ',
- 'second' => '{1}ಕೆಲವು ಕ್ಷಣಗಳು|]1,Inf[:count ಸೆಕೆಂಡುಗಳು',
- 'ago' => ':time ಹಿಂದೆ',
- 'from_now' => ':time ನಂತರ',
- 'diff_yesterday' => 'ನಿನ್ನೆ',
- 'diff_tomorrow' => 'ನಾಳೆ',
- 'formats' => [
- 'LT' => 'A h:mm',
- 'LTS' => 'A h:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[ಇಂದು] LT',
- 'nextDay' => '[ನಾಳೆ] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[ನಿನ್ನೆ] LT',
- 'lastWeek' => '[ಕೊನೆಯ] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberನೇ',
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'ರಾತ್ರಿ';
- }
- if ($hour < 10) {
- return 'ಬೆಳಿಗ್ಗೆ';
- }
- if ($hour < 17) {
- return 'ಮಧ್ಯಾಹ್ನ';
- }
- if ($hour < 20) {
- return 'ಸಂಜೆ';
- }
-
- return 'ರಾತ್ರಿ';
- },
- 'months' => ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'],
- 'months_short' => ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ', 'ಡಿಸೆಂ'],
- 'weekdays' => ['ಭಾನುವಾರ', 'ಸೋಮವಾರ', 'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
- 'weekdays_short' => ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ', 'ಬುಧ', 'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
- 'weekdays_min' => ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
- 'list' => ', ',
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/kn.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kunal Marwaha
- * - FourwingsY
- * - François B
- * - Jason Katz-Brown
- * - Seokjun Kim
- * - Junho Kim
- * - JD Isaacks
- * - Juwon Kim
- */
-return [
- 'year' => '{1}일 년|]1,Inf[:count년',
- 'y' => ':count 년',
- 'month' => '{1}한 달|]1,Inf[:count달',
- 'm' => ':count 개월',
- 'week' => ':count 주일',
- 'w' => ':count 주일',
- 'day' => '{1}하루|]1,Inf[:count일',
- 'd' => ':count 일',
- 'hour' => '{1}한 시간|]1,Inf[:count시간',
- 'h' => ':count 시간',
- 'minute' => '{1}1분|]1,Inf[:count분',
- 'min' => ':count 분',
- 'second' => '{1}몇 초|]1,Inf[:count초',
- 's' => ':count 초',
- 'ago' => ':time 전',
- 'from_now' => ':time 후',
- 'after' => ':time 이후',
- 'before' => ':time 이전',
- 'formats' => [
- 'LT' => 'A h:mm',
- 'LTS' => 'A h:mm:ss',
- 'L' => 'YYYY.MM.DD.',
- 'LL' => 'YYYY년 MMMM D일',
- 'LLL' => 'YYYY년 MMMM D일 A h:mm',
- 'LLLL' => 'YYYY년 MMMM D일 dddd A h:mm',
- ],
- 'calendar' => [
- 'sameDay' => '오늘 LT',
- 'nextDay' => '내일 LT',
- 'nextWeek' => 'dddd LT',
- 'lastDay' => '어제 LT',
- 'lastWeek' => '지난주 dddd LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'일';
- case 'M':
- return $number.'월';
- case 'w':
- case 'W':
- return $number.'주';
- default:
- return $number;
- }
- },
- 'meridiem' => ['오전', '오후'],
- 'months' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
- 'months_short' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
- 'weekdays' => ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
- 'weekdays_short' => ['일', '월', '화', '수', '목', '금', '토'],
- 'weekdays_min' => ['일', '월', '화', '수', '목', '금', '토'],
- 'list' => ' ',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ko.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ko.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/kok_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat, Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D-M-YY',
- ],
- 'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
- 'months_short' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
- 'weekdays' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
- 'weekdays_short' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
- 'weekdays_min' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['म.पू.', 'म.नं.'],
-
- 'year' => ':count वैशाकु', // less reliable
- 'y' => ':count वैशाकु', // less reliable
- 'a_year' => ':count वैशाकु', // less reliable
-
- 'week' => ':count आदित्यवार', // less reliable
- 'w' => ':count आदित्यवार', // less reliable
- 'a_week' => ':count आदित्यवार', // less reliable
-
- 'minute' => ':count नोंद', // less reliable
- 'min' => ':count नोंद', // less reliable
- 'a_minute' => ':count नोंद', // less reliable
-
- 'second' => ':count तेंको', // less reliable
- 's' => ':count तेंको', // less reliable
- 'a_second' => ':count तेंको', // less reliable
-
- 'month' => ':count मैनो',
- 'm' => ':count मैनो',
- 'a_month' => ':count मैनो',
-
- 'day' => ':count दिवसु',
- 'd' => ':count दिवसु',
- 'a_day' => ':count दिवसु',
-
- 'hour' => ':count घंते',
- 'h' => ':count घंते',
- 'a_hour' => ':count घंते',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ks_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat, Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'M/D/YY',
- ],
- 'months' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
- 'weekdays' => ['آتهوار', 'ژءندروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
- 'weekdays_short' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
- 'weekdays_min' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['دوپھربرونھ', 'دوپھرپتھ'],
-
- 'year' => ':count آب', // less reliable
- 'y' => ':count آب', // less reliable
- 'a_year' => ':count آب', // less reliable
-
- 'month' => ':count रान्', // less reliable
- 'm' => ':count रान्', // less reliable
- 'a_month' => ':count रान्', // less reliable
-
- 'week' => ':count آتھٕوار', // less reliable
- 'w' => ':count آتھٕوار', // less reliable
- 'a_week' => ':count آتھٕوار', // less reliable
-
- 'hour' => ':count سۄن', // less reliable
- 'h' => ':count سۄن', // less reliable
- 'a_hour' => ':count سۄن', // less reliable
-
- 'minute' => ':count فَن', // less reliable
- 'min' => ':count فَن', // less reliable
- 'a_minute' => ':count فَن', // less reliable
-
- 'second' => ':count दोʼयुम', // less reliable
- 's' => ':count दोʼयुम', // less reliable
- 'a_second' => ':count दोʼयुम', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - ks-gnome-trans-commits@lists.code.indlinux.net
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'M/D/YY',
- ],
- 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'weekdays' => ['आथवार', 'चॅ़दुरवार', 'बोमवार', 'ब्वदवार', 'ब्रसवार', 'शोकुरवार', 'बटुवार'],
- 'weekdays_short' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'],
- 'weekdays_min' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['makeo', 'nyiaghuo'],
- 'weekdays' => ['Jumaapii', 'Jumaatatu', 'Jumaane', 'Jumaatano', 'Alhamisi', 'Ijumaa', 'Jumaamosi'],
- 'weekdays_short' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'months' => ['Januali', 'Febluali', 'Machi', 'Aplili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['sárúwá', 'cɛɛ́nko'],
- 'weekdays' => ['sɔ́ndǝ', 'lǝndí', 'maadí', 'mɛkrɛdí', 'jǝǝdí', 'júmbá', 'samdí'],
- 'weekdays_short' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
- 'weekdays_min' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
- 'months' => ['ŋwíí a ntɔ́ntɔ', 'ŋwíí akǝ bɛ́ɛ', 'ŋwíí akǝ ráá', 'ŋwíí akǝ nin', 'ŋwíí akǝ táan', 'ŋwíí akǝ táafɔk', 'ŋwíí akǝ táabɛɛ', 'ŋwíí akǝ táaraa', 'ŋwíí akǝ táanin', 'ŋwíí akǝ ntɛk', 'ŋwíí akǝ ntɛk di bɔ́k', 'ŋwíí akǝ ntɛk di bɛ́ɛ'],
- 'months_short' => ['ŋ1', 'ŋ2', 'ŋ3', 'ŋ4', 'ŋ5', 'ŋ6', 'ŋ7', 'ŋ8', 'ŋ9', 'ŋ10', 'ŋ11', 'ŋ12'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['v.M.', 'n.M.'],
- 'weekdays' => ['Sunndaach', 'Mohndaach', 'Dinnsdaach', 'Metwoch', 'Dunnersdaach', 'Friidaach', 'Samsdaach'],
- 'weekdays_short' => ['Su.', 'Mo.', 'Di.', 'Me.', 'Du.', 'Fr.', 'Sa.'],
- 'weekdays_min' => ['Su', 'Mo', 'Di', 'Me', 'Du', 'Fr', 'Sa'],
- 'months' => ['Jannewa', 'Fäbrowa', 'Määz', 'Aprell', 'Mai', 'Juuni', 'Juuli', 'Oujoß', 'Septämber', 'Oktohber', 'Novämber', 'Dezämber'],
- 'months_short' => ['Jan', 'Fäb', 'Mäz', 'Apr', 'Mai', 'Jun', 'Jul', 'Ouj', 'Säp', 'Okt', 'Nov', 'Dez'],
- 'months_short_standalone' => ['Jan.', 'Fäb.', 'Mäz.', 'Apr.', 'Mai', 'Jun.', 'Jul.', 'Ouj.', 'Säp.', 'Okt.', 'Nov.', 'Dez.'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D. M. YYYY',
- 'LL' => 'D. MMM. YYYY',
- 'LLL' => 'D. MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, [dä] D. MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count Johr',
- 'y' => ':count Johr',
- 'a_year' => ':count Johr',
-
- 'month' => ':count Moohnd',
- 'm' => ':count Moohnd',
- 'a_month' => ':count Moohnd',
-
- 'week' => ':count woch',
- 'w' => ':count woch',
- 'a_week' => ':count woch',
-
- 'day' => ':count Daach',
- 'd' => ':count Daach',
- 'a_day' => ':count Daach',
-
- 'hour' => ':count Uhr',
- 'h' => ':count Uhr',
- 'a_hour' => ':count Uhr',
-
- 'minute' => ':count Menutt',
- 'min' => ':count Menutt',
- 'a_minute' => ':count Menutt',
-
- 'second' => ':count Sekůndt',
- 's' => ':count Sekůndt',
- 'a_second' => ':count Sekůndt',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Halwest Manguri
- */
-$months = ['کانونی دووەم', 'شوبات', 'ئازار', 'نیسان', 'ئایار', 'حوزەیران', 'تەمموز', 'ئاب', 'ئەیلول', 'تشرینی یەکەم', 'تشرینی دووەم', 'کانونی یەکەم'];
-
-$weekdays = ['دوو شەممە', 'سێ شەممە', 'چوار شەممە', 'پێنج شەممە', 'هەینی', 'شەممە', 'یەک شەممە'];
-
-return [
- 'ago' => 'لەمەوبەر :time',
- 'from_now' => ':time لە ئێستاوە',
- 'after' => 'دوای :time',
- 'before' => 'پێش :time',
- 'year' => '{0}ساڵ|{1}ساڵ|{2}ساڵ|[3,10]:count ساڵ|[11,Inf]:count ساڵ',
- 'month' => '{0}مانگ|{1}مانگ|{2}مانگ|[3,10]:count مانگ|[11,Inf]:count مانگ',
- 'week' => '{0}هەفتە|{1}هەفتە|{2}هەفتە|[3,10]:count هەفتە|[11,Inf]:count هەفتە',
- 'day' => '{0}ڕۆژ|{1}ڕۆژ|{2}ڕۆژ|[3,10]:count ڕۆژ|[11,Inf]:count ڕۆژ',
- 'hour' => '{0}کاژێر|{1}کاژێر|{2}کاژێر|[3,10]:count کاژێر|[11,Inf]:count کاژێر',
- 'minute' => '{0}خولەک|{1}خولەک|{2}خولەک|[3,10]:count خولەک|[11,Inf]:count خولەک',
- 'second' => '{0}چرکە|{1}چرکە|{2}چرکە|[3,10]:count چرکە|[11,Inf]:count چرکە',
- 'months' => $months,
- 'months_standalone' => $months,
- 'months_short' => $months,
- 'weekdays' => $weekdays,
- 'weekdays_short' => $weekdays,
- 'weekdays_min' => $weekdays,
- 'list' => [', ', ' û '],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ku.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/kw_GB.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Alastair McKinstry bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['mis Genver', 'mis Hwevrer', 'mis Meurth', 'mis Ebrel', 'mis Me', 'mis Metheven', 'mis Gortheren', 'mis Est', 'mis Gwynngala', 'mis Hedra', 'mis Du', 'mis Kevardhu'],
- 'months_short' => ['Gen', 'Hwe', 'Meu', 'Ebr', 'Me', 'Met', 'Gor', 'Est', 'Gwn', 'Hed', 'Du', 'Kev'],
- 'weekdays' => ['De Sul', 'De Lun', 'De Merth', 'De Merher', 'De Yow', 'De Gwener', 'De Sadorn'],
- 'weekdays_short' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
- 'weekdays_min' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count bledhen',
- 'y' => ':count bledhen',
- 'a_year' => ':count bledhen',
-
- 'month' => ':count mis',
- 'm' => ':count mis',
- 'a_month' => ':count mis',
-
- 'week' => ':count seythen',
- 'w' => ':count seythen',
- 'a_week' => ':count seythen',
-
- 'day' => ':count dydh',
- 'd' => ':count dydh',
- 'a_day' => ':count dydh',
-
- 'hour' => ':count eur',
- 'h' => ':count eur',
- 'a_hour' => ':count eur',
-
- 'minute' => ':count mynysen',
- 'min' => ':count mynysen',
- 'a_minute' => ':count mynysen',
-
- 'second' => ':count pryjwyth',
- 's' => ':count pryjwyth',
- 'a_second' => ':count pryjwyth',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'ky');
-
-/*
- * Authors:
- * - acutexyz
- * - Josh Soref
- * - François B
- * - Chyngyz Arystan uulu
- * - Chyngyz
- * - acutexyz
- * - Josh Soref
- * - François B
- * - Chyngyz Arystan uulu
- */
-return [
- 'year' => ':count жыл',
- 'a_year' => 'бир жыл|:count жыл',
- 'y' => ':count жыл',
- 'month' => ':count ай',
- 'a_month' => 'бир ай|:count ай',
- 'm' => ':count ай',
- 'week' => ':count апта',
- 'a_week' => 'бир апта|:count апта',
- 'w' => ':count апт.',
- 'day' => ':count күн',
- 'a_day' => 'бир күн|:count күн',
- 'd' => ':count күн',
- 'hour' => ':count саат',
- 'a_hour' => 'бир саат|:count саат',
- 'h' => ':count саат.',
- 'minute' => ':count мүнөт',
- 'a_minute' => 'бир мүнөт|:count мүнөт',
- 'min' => ':count мүн.',
- 'second' => ':count секунд',
- 'a_second' => 'бирнече секунд|:count секунд',
- 's' => ':count сек.',
- 'ago' => ':time мурун',
- 'from_now' => ':time ичинде',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Бүгүн саат] LT',
- 'nextDay' => '[Эртең саат] LT',
- 'nextWeek' => 'dddd [саат] LT',
- 'lastDay' => '[Кече саат] LT',
- 'lastWeek' => '[Өткен аптанын] dddd [күнү] [саат] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- static $suffixes = [
- 0 => '-чү',
- 1 => '-чи',
- 2 => '-чи',
- 3 => '-чү',
- 4 => '-чү',
- 5 => '-чи',
- 6 => '-чы',
- 7 => '-чи',
- 8 => '-чи',
- 9 => '-чу',
- 10 => '-чу',
- 20 => '-чы',
- 30 => '-чу',
- 40 => '-чы',
- 50 => '-чү',
- 60 => '-чы',
- 70 => '-чи',
- 80 => '-чи',
- 90 => '-чу',
- 100 => '-чү',
- ];
-
- return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
- },
- 'months' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
- 'months_short' => ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'weekdays' => ['Жекшемби', 'Дүйшөмбү', 'Шейшемби', 'Шаршемби', 'Бейшемби', 'Жума', 'Ишемби'],
- 'weekdays_short' => ['Жек', 'Дүй', 'Шей', 'Шар', 'Бей', 'Жум', 'Ише'],
- 'weekdays_min' => ['Жк', 'Дй', 'Шй', 'Шр', 'Бй', 'Жм', 'Иш'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => ' ',
- 'meridiem' => ['таңкы', 'түштөн кийинки'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ky.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['TOO', 'MUU'],
- 'weekdays' => ['Jumapíiri', 'Jumatátu', 'Jumaíne', 'Jumatáano', 'Alamíisi', 'Ijumáa', 'Jumamóosi'],
- 'weekdays_short' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
- 'weekdays_min' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
- 'months' => ['Kʉfúngatɨ', 'Kʉnaanɨ', 'Kʉkeenda', 'Kwiikumi', 'Kwiinyambála', 'Kwiidwaata', 'Kʉmʉʉnchɨ', 'Kʉvɨɨrɨ', 'Kʉsaatʉ', 'Kwiinyi', 'Kʉsaano', 'Kʉsasatʉ'],
- 'months_short' => ['Fúngatɨ', 'Naanɨ', 'Keenda', 'Ikúmi', 'Inyambala', 'Idwaata', 'Mʉʉnchɨ', 'Vɨɨrɨ', 'Saatʉ', 'Inyi', 'Saano', 'Sasatʉ'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - dan-nl
- */
-return [
- 'year' => ':count Joer',
- 'y' => ':countJ',
- 'month' => ':count Mount|:count Méint',
- 'm' => ':countMo',
- 'week' => ':count Woch|:count Wochen',
- 'w' => ':countWo|:countWo',
- 'day' => ':count Dag|:count Deeg',
- 'd' => ':countD',
- 'hour' => ':count Stonn|:count Stonnen',
- 'h' => ':countSto',
- 'minute' => ':count Minutt|:count Minutten',
- 'min' => ':countM',
- 'second' => ':count Sekonnen',
- 's' => ':countSek',
-
- 'formats' => [
- 'LT' => 'H:mm [Auer]',
- 'LTS' => 'H:mm:ss [Auer]',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm [Auer]',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm [Auer]',
- ],
-
- 'calendar' => [
- 'sameDay' => '[Haut um] LT',
- 'nextDay' => '[Muer um] LT',
- 'nextWeek' => 'dddd [um] LT',
- 'lastDay' => '[Gëschter um] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
- switch ($date->dayOfWeek) {
- case 2:
- case 4:
- return '[Leschten] dddd [um] LT';
- default:
- return '[Leschte] dddd [um] LT';
- }
- },
- 'sameElse' => 'L',
- ],
-
- 'months' => ['Januar', 'Februar', 'Mäerz', 'Abrëll', 'Mee', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
- 'months_short' => ['Jan.', 'Febr.', 'Mrz.', 'Abr.', 'Mee', 'Jun.', 'Jul.', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dez.'],
- 'weekdays' => ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],
- 'weekdays_short' => ['So.', 'Mé.', 'Dë.', 'Më.', 'Do.', 'Fr.', 'Sa.'],
- 'weekdays_min' => ['So', 'Mé', 'Dë', 'Më', 'Do', 'Fr', 'Sa'],
- 'ordinal' => ':number.',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' an '],
- 'meridiem' => ['moies', 'mëttes'],
- 'weekdays_short_standalone' => ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
- 'months_short_standalone' => ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/lb.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/lg_UG.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Akademe ya Luganda Kizito Birabwa kompyuta@kizito.uklinux.net
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
- 'weekdays' => ['Sabiiti', 'Balaza', 'Lwakubiri', 'Lwakusatu', 'Lwakuna', 'Lwakutaano', 'Lwamukaaga'],
- 'weekdays_short' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
- 'weekdays_min' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'month' => ':count njuba', // less reliable
- 'm' => ':count njuba', // less reliable
- 'a_month' => ':count njuba', // less reliable
-
- 'year' => ':count mwaaka',
- 'y' => ':count mwaaka',
- 'a_year' => ':count mwaaka',
-
- 'week' => ':count sabbiiti',
- 'w' => ':count sabbiiti',
- 'a_week' => ':count sabbiiti',
-
- 'day' => ':count lunaku',
- 'd' => ':count lunaku',
- 'a_day' => ':count lunaku',
-
- 'hour' => 'saawa :count',
- 'h' => 'saawa :count',
- 'a_hour' => 'saawa :count',
-
- 'minute' => 'ddakiika :count',
- 'min' => 'ddakiika :count',
- 'a_minute' => 'ddakiika :count',
-
- 'second' => ':count kyʼokubiri',
- 's' => ':count kyʼokubiri',
- 'a_second' => ':count kyʼokubiri',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/li_NL.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['jannewarie', 'fibberwarie', 'miert', 'eprèl', 'meij', 'junie', 'julie', 'augustus', 'september', 'oktober', 'november', 'desember'],
- 'months_short' => ['jan', 'fib', 'mie', 'epr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
- 'weekdays' => ['zóndig', 'maondig', 'daensdig', 'goonsdig', 'dónderdig', 'vriedig', 'zaoterdig'],
- 'weekdays_short' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'],
- 'weekdays_min' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'minute' => ':count momênt', // less reliable
- 'min' => ':count momênt', // less reliable
- 'a_minute' => ':count momênt', // less reliable
-
- 'year' => ':count jaor',
- 'y' => ':count jaor',
- 'a_year' => ':count jaor',
-
- 'month' => ':count maond',
- 'm' => ':count maond',
- 'a_month' => ':count maond',
-
- 'week' => ':count waek',
- 'w' => ':count waek',
- 'a_week' => ':count waek',
-
- 'day' => ':count daag',
- 'd' => ':count daag',
- 'a_day' => ':count daag',
-
- 'hour' => ':count oer',
- 'h' => ':count oer',
- 'a_hour' => ':count oer',
-
- 'second' => ':count Secónd',
- 's' => ':count Secónd',
- 'a_second' => ':count Secónd',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/lij_IT.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Gastaldi alessio.gastaldi@libero.it
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['zenâ', 'fevrâ', 'marzo', 'avrî', 'mazzo', 'zûgno', 'lûggio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dixembre'],
- 'months_short' => ['zen', 'fev', 'mar', 'arv', 'maz', 'zûg', 'lûg', 'ago', 'set', 'ött', 'nov', 'dix'],
- 'weekdays' => ['domenega', 'lûnedì', 'martedì', 'mercUrdì', 'zêggia', 'venardì', 'sabbo'],
- 'weekdays_short' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'],
- 'weekdays_min' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count etæ', // less reliable
- 'y' => ':count etæ', // less reliable
- 'a_year' => ':count etæ', // less reliable
-
- 'month' => ':count meize',
- 'm' => ':count meize',
- 'a_month' => ':count meize',
-
- 'week' => ':count settemannha',
- 'w' => ':count settemannha',
- 'a_week' => ':count settemannha',
-
- 'day' => ':count giorno',
- 'd' => ':count giorno',
- 'a_day' => ':count giorno',
-
- 'hour' => ':count reléuio', // less reliable
- 'h' => ':count reléuio', // less reliable
- 'a_hour' => ':count reléuio', // less reliable
-
- 'minute' => ':count menûo',
- 'min' => ':count menûo',
- 'a_minute' => ':count menûo',
-
- 'second' => ':count segondo',
- 's' => ':count segondo',
- 'a_second' => ':count segondo',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
-
- 'month' => ':count haŋwí', // less reliable
- 'm' => ':count haŋwí', // less reliable
- 'a_month' => ':count haŋwí', // less reliable
-
- 'week' => ':count šakówiŋ', // less reliable
- 'w' => ':count šakówiŋ', // less reliable
- 'a_week' => ':count šakówiŋ', // less reliable
-
- 'hour' => ':count maza škaŋškaŋ', // less reliable
- 'h' => ':count maza škaŋškaŋ', // less reliable
- 'a_hour' => ':count maza škaŋškaŋ', // less reliable
-
- 'minute' => ':count číkʼala', // less reliable
- 'min' => ':count číkʼala', // less reliable
- 'a_minute' => ':count číkʼala', // less reliable
-
- 'year' => ':count waníyetu',
- 'y' => ':count waníyetu',
- 'a_year' => ':count waníyetu',
-
- 'day' => ':count aŋpétu',
- 'd' => ':count aŋpétu',
- 'a_day' => ':count aŋpétu',
-
- 'second' => ':count icinuŋpa',
- 's' => ':count icinuŋpa',
- 'a_second' => ':count icinuŋpa',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'months' => ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́', 'sánzá ya zómi na míbalé'],
- 'months_short' => ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
- 'weekdays' => ['Lomíngo', 'Mosálá mɔ̌kɔ́', 'Misálá míbalé', 'Misálá mísáto', 'Misálá mínei', 'Misálá mítáno', 'Mpɔ́sɔ'],
- 'weekdays_short' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'],
- 'weekdays_min' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => 'mbula :count',
- 'y' => 'mbula :count',
- 'a_year' => 'mbula :count',
-
- 'month' => 'sánzá :count',
- 'm' => 'sánzá :count',
- 'a_month' => 'sánzá :count',
-
- 'week' => 'mpɔ́sɔ :count',
- 'w' => 'mpɔ́sɔ :count',
- 'a_week' => 'mpɔ́sɔ :count',
-
- 'day' => 'mokɔlɔ :count',
- 'd' => 'mokɔlɔ :count',
- 'a_day' => 'mokɔlɔ :count',
-
- 'hour' => 'ngonga :count',
- 'h' => 'ngonga :count',
- 'a_hour' => 'ngonga :count',
-
- 'minute' => 'miniti :count',
- 'min' => 'miniti :count',
- 'a_minute' => 'miniti :count',
-
- 'second' => 'segɔnde :count',
- 's' => 'segɔnde :count',
- 'a_second' => 'segɔnde :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ln.php', [
- 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
- 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
- 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
- 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com
- */
-return require __DIR__.'/ln.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ln.php', [
- 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
- 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
- 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
- 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ln.php', [
- 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
- 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
- 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
- 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'lo');
-
-/*
- * Authors:
- * - François B
- * - ryanhart2
- */
-return [
- 'year' => ':count ປີ',
- 'y' => ':count ປີ',
- 'month' => ':count ເດືອນ',
- 'm' => ':count ດ. ',
- 'week' => ':count ອາທິດ',
- 'w' => ':count ອທ. ',
- 'day' => ':count ມື້',
- 'd' => ':count ມື້',
- 'hour' => ':count ຊົ່ວໂມງ',
- 'h' => ':count ຊມ. ',
- 'minute' => ':count ນາທີ',
- 'min' => ':count ນທ. ',
- 'second' => 'ບໍ່ເທົ່າໃດວິນາທີ|:count ວິນາທີ',
- 's' => ':count ວິ. ',
- 'ago' => ':timeຜ່ານມາ',
- 'from_now' => 'ອີກ :time',
- 'diff_yesterday' => 'ມື້ວານນີ້ເວລາ',
- 'diff_tomorrow' => 'ມື້ອື່ນເວລາ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'ວັນdddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[ມື້ນີ້ເວລາ] LT',
- 'nextDay' => '[ມື້ອື່ນເວລາ] LT',
- 'nextWeek' => '[ວັນ]dddd[ໜ້າເວລາ] LT',
- 'lastDay' => '[ມື້ວານນີ້ເວລາ] LT',
- 'lastWeek' => '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => 'ທີ່:number',
- 'meridiem' => ['ຕອນເຊົ້າ', 'ຕອນແລງ'],
- 'months' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
- 'months_short' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
- 'weekdays' => ['ອາທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'],
- 'weekdays_short' => ['ທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'],
- 'weekdays_min' => ['ທ', 'ຈ', 'ອຄ', 'ພ', 'ພຫ', 'ສກ', 'ສ'],
- 'list' => [', ', 'ແລະ '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/lo.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
-
- 'minute' => ':count هنر', // less reliable
- 'min' => ':count هنر', // less reliable
- 'a_minute' => ':count هنر', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/lrc.php', [
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - tjku
- * - valdas406
- * - Justas Palumickas
- * - Max Melentiev
- * - Andrius Janauskas
- * - Juanito Fatas
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Nicolás Hock Isaza
- * - Laurynas Butkus
- * - Sven Fuchs
- * - Dominykas Tijūnaitis
- * - Justinas Bolys
- * - Ričardas
- * - Kirill Chalkin
- * - Rolandas
- */
-return [
- 'year' => ':count metus|:count metus|:count metų',
- 'y' => ':count metus|:count metus|:count metų',
- 'month' => ':count mėnesį|:count mėnesius|:count mėnesių',
- 'm' => ':count mėnesį|:count mėnesius|:count mėnesių',
- 'week' => ':count savaitę|:count savaites|:count savaičių',
- 'w' => ':count savaitę|:count savaites|:count savaičių',
- 'day' => ':count dieną|:count dienas|:count dienų',
- 'd' => ':count dieną|:count dienas|:count dienų',
- 'hour' => ':count valandą|:count valandas|:count valandų',
- 'h' => ':count valandą|:count valandas|:count valandų',
- 'minute' => ':count minutę|:count minutes|:count minučių',
- 'min' => ':count minutę|:count minutes|:count minučių',
- 'second' => ':count sekundę|:count sekundes|:count sekundžių',
- 's' => ':count sekundę|:count sekundes|:count sekundžių',
- 'second_from_now' => ':count sekundės|:count sekundžių|:count sekundžių',
- 'minute_from_now' => ':count minutės|:count minučių|:count minučių',
- 'hour_from_now' => ':count valandos|:count valandų|:count valandų',
- 'day_from_now' => ':count dienos|:count dienų|:count dienų',
- 'week_from_now' => ':count savaitės|:count savaičių|:count savaičių',
- 'month_from_now' => ':count mėnesio|:count mėnesių|:count mėnesių',
- 'year_from_now' => ':count metų',
- 'ago' => 'prieš :time',
- 'from_now' => 'už :time',
- 'after' => 'po :time',
- 'before' => ':time nuo dabar',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'diff_now' => 'ką tik',
- 'diff_yesterday' => 'vakar',
- 'diff_tomorrow' => 'rytoj',
- 'diff_before_yesterday' => 'užvakar',
- 'diff_after_tomorrow' => 'poryt',
- 'period_recurrences' => 'kartą|:count kartų',
- 'period_interval' => 'kiekvieną :interval',
- 'period_start_date' => 'nuo :date',
- 'period_end_date' => 'iki :date',
- 'months' => ['Sausis', 'Vasaris', 'Kovas', 'Balandis', 'Gegužė', 'Birželis', 'Liepa', 'Rugpjūtis', 'Rugsėjis', 'Spalis', 'Lapkritis', 'Gruodis'],
- 'months_short' => ['Sau', 'Vas', 'Kov', 'Bal', 'Geg', 'Bir', 'Lie', 'Rgp', 'Rgs', 'Spa', 'Lap', 'Gru'],
- 'weekdays' => ['Sekmadienis', 'Pirmadienis', 'Antradienis', 'Trečiadienis', 'Ketvirtadienis', 'Penktadienis', 'Šeštadienis'],
- 'weekdays_short' => ['Sek', 'Pir', 'Ant', 'Tre', 'Ket', 'Pen', 'Šeš'],
- 'weekdays_min' => ['Se', 'Pi', 'An', 'Tr', 'Ke', 'Pe', 'Še'],
- 'list' => [', ', ' ir '],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'MMMM DD, YYYY',
- 'LLL' => 'DD MMM HH:mm',
- 'LLLL' => 'MMMM DD, YYYY HH:mm',
- ],
- 'meridiem' => ['priešpiet', 'popiet'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/lt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Dinda', 'Dilolo'],
- 'weekdays' => ['Lumingu', 'Nkodya', 'Ndàayà', 'Ndangù', 'Njòwa', 'Ngòvya', 'Lubingu'],
- 'weekdays_short' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
- 'weekdays_min' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
- 'months' => ['Ciongo', 'Lùishi', 'Lusòlo', 'Mùuyà', 'Lumùngùlù', 'Lufuimi', 'Kabàlàshìpù', 'Lùshìkà', 'Lutongolo', 'Lungùdi', 'Kaswèkèsè', 'Ciswà'],
- 'months_short' => ['Cio', 'Lui', 'Lus', 'Muu', 'Lum', 'Luf', 'Kab', 'Lush', 'Lut', 'Lun', 'Kas', 'Cis'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['OD', 'OT'],
- 'weekdays' => ['Jumapil', 'Wuok Tich', 'Tich Ariyo', 'Tich Adek', 'Tich Ang’wen', 'Tich Abich', 'Ngeso'],
- 'weekdays_short' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
- 'weekdays_min' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
- 'months' => ['Dwe mar Achiel', 'Dwe mar Ariyo', 'Dwe mar Adek', 'Dwe mar Ang’wen', 'Dwe mar Abich', 'Dwe mar Auchiel', 'Dwe mar Abiriyo', 'Dwe mar Aboro', 'Dwe mar Ochiko', 'Dwe mar Apar', 'Dwe mar gi achiel', 'Dwe mar Apar gi ariyo'],
- 'months_short' => ['DAC', 'DAR', 'DAD', 'DAN', 'DAH', 'DAU', 'DAO', 'DAB', 'DOC', 'DAP', 'DGI', 'DAG'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'year' => 'higni :count',
- 'y' => 'higni :count',
- 'a_year' => ':higni :count',
-
- 'month' => 'dweche :count',
- 'm' => 'dweche :count',
- 'a_month' => 'dweche :count',
-
- 'week' => 'jumbe :count',
- 'w' => 'jumbe :count',
- 'a_week' => 'jumbe :count',
-
- 'day' => 'ndalo :count',
- 'd' => 'ndalo :count',
- 'a_day' => 'ndalo :count',
-
- 'hour' => 'seche :count',
- 'h' => 'seche :count',
- 'a_hour' => 'seche :count',
-
- 'minute' => 'dakika :count',
- 'min' => 'dakika :count',
- 'a_minute' => 'dakika :count',
-
- 'second' => 'nus dakika :count',
- 's' => 'nus dakika :count',
- 'a_second' => 'nus dakika :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Jumapiri', 'Jumatatu', 'Jumanne', 'Jumatano', 'Murwa wa Kanne', 'Murwa wa Katano', 'Jumamosi'],
- 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
- 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- // Too unreliable
- /*
- 'year' => ':count liliino', // less reliable
- 'y' => ':count liliino', // less reliable
- 'a_year' => ':count liliino', // less reliable
-
- 'month' => ':count kumwesi', // less reliable
- 'm' => ':count kumwesi', // less reliable
- 'a_month' => ':count kumwesi', // less reliable
-
- 'week' => ':count olutambi', // less reliable
- 'w' => ':count olutambi', // less reliable
- 'a_week' => ':count olutambi', // less reliable
-
- 'day' => ':count luno', // less reliable
- 'd' => ':count luno', // less reliable
- 'a_day' => ':count luno', // less reliable
-
- 'hour' => ':count ekengele', // less reliable
- 'h' => ':count ekengele', // less reliable
- 'a_hour' => ':count ekengele', // less reliable
-
- 'minute' => ':count omundu', // less reliable
- 'min' => ':count omundu', // less reliable
- 'a_minute' => ':count omundu', // less reliable
-
- 'second' => ':count liliino', // less reliable
- 's' => ':count liliino', // less reliable
- 'a_second' => ':count liliino', // less reliable
- */
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - pirminis
- * - Tsutomu Kuroda
- * - tjku
- * - Andris Zāģeris
- * - Max Melentiev
- * - Edgars Beigarts
- * - Juanito Fatas
- * - Vitauts Stočka
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Kaspars Bankovskis
- * - Nicolás Hock Isaza
- * - Kavacky
- */
-return [
- 'year' => '0 gadiem|:count gada|:count gadiem',
- 'y' => '0 gadiem|:count gada|:count gadiem',
- 'month' => '0 mēnešiem|:count mēneša|:count mēnešiem',
- 'm' => '0 mēnešiem|:count mēneša|:count mēnešiem',
- 'week' => '0 nedēļām|:count nedēļas|:count nedēļām',
- 'w' => '0 nedēļām|:count nedēļas|:count nedēļām',
- 'day' => '0 dienām|:count dienas|:count dienām',
- 'd' => '0 dienām|:count dienas|:count dienām',
- 'hour' => '0 stundām|:count stundas|:count stundām',
- 'h' => '0 stundām|:count stundas|:count stundām',
- 'minute' => '0 minūtēm|:count minūtes|:count minūtēm',
- 'min' => '0 minūtēm|:count minūtes|:count minūtēm',
- 'second' => '0 sekundēm|:count sekundes|:count sekundēm',
- 's' => '0 sekundēm|:count sekundes|:count sekundēm',
- 'ago' => 'pirms :time',
- 'from_now' => 'pēc :time',
- 'after' => ':time vēlāk',
- 'before' => ':time pirms',
-
- 'year_after' => '0 gadus|:count gadu|:count gadus',
- 'month_after' => '0 mēnešus|:count mēnesi|:count mēnešus',
- 'week_after' => '0 nedēļas|:count nedēļu|:count nedēļas',
- 'day_after' => '0 dienas|:count dienu|:count dienas',
- 'hour_after' => '0 stundas|:count stundu|:count stundas',
- 'minute_after' => '0 minūtes|:count minūti|:count minūtes',
- 'second_after' => '0 sekundes|:count sekundi|:count sekundes',
-
- 'year_before' => '0 gadus|:count gadu|:count gadus',
- 'month_before' => '0 mēnešus|:count mēnesi|:count mēnešus',
- 'week_before' => '0 nedēļas|:count nedēļu|:count nedēļas',
- 'day_before' => '0 dienas|:count dienu|:count dienas',
- 'hour_before' => '0 stundas|:count stundu|:count stundas',
- 'minute_before' => '0 minūtes|:count minūti|:count minūtes',
- 'second_before' => '0 sekundes|:count sekundi|:count sekundes',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' un '],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY.',
- 'LL' => 'YYYY. [gada] D. MMMM',
- 'LLL' => 'DD.MM.YYYY., HH:mm',
- 'LLLL' => 'YYYY. [gada] D. MMMM, HH:mm',
- ],
- 'weekdays' => ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena', 'piektdiena', 'sestdiena'],
- 'weekdays_short' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'],
- 'weekdays_min' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'],
- 'months' => ['janvārī', 'ferbruārī', 'martā', 'aprīlī', 'maijā', 'jūnijā', 'jūlijā', 'augustā', 'septembrī', 'oktobrī', 'novembrī', 'decembrī'],
- 'months_short' => ['Janv', 'Febr', 'Marts', 'Apr', 'Maijs', 'Jūn', 'Jūl', 'Aug', 'Sept', 'Okt', 'Nov', 'Dec'],
- 'meridiem' => ['priekšpusdiena', 'pēcpusdiena'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/lv.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/lzh_TW.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'OY[年]MMMMOD[日]',
- ],
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => [' 一 ', ' 二 ', ' 三 ', ' 四 ', ' 五 ', ' 六 ', ' 七 ', ' 八 ', ' 九 ', ' 十 ', '十一', '十二'],
- 'weekdays' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
- 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'day_of_first_week_of_year' => 1,
- 'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '廿', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '卅', '卅一'],
- 'meridiem' => ['朝', '暮'],
-
- 'year' => ':count 夏', // less reliable
- 'y' => ':count 夏', // less reliable
- 'a_year' => ':count 夏', // less reliable
-
- 'month' => ':count 月', // less reliable
- 'm' => ':count 月', // less reliable
- 'a_month' => ':count 月', // less reliable
-
- 'hour' => ':count 氧', // less reliable
- 'h' => ':count 氧', // less reliable
- 'a_hour' => ':count 氧', // less reliable
-
- 'minute' => ':count 點', // less reliable
- 'min' => ':count 點', // less reliable
- 'a_minute' => ':count 點', // less reliable
-
- 'second' => ':count 楚', // less reliable
- 's' => ':count 楚', // less reliable
- 'a_second' => ':count 楚', // less reliable
-
- 'week' => ':count 星期',
- 'w' => ':count 星期',
- 'a_week' => ':count 星期',
-
- 'day' => ':count 日(曆法)',
- 'd' => ':count 日(曆法)',
- 'a_day' => ':count 日(曆法)',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mag_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bhashaghar@googlegroups.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'weekdays' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
- 'weekdays_short' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
- 'weekdays_min' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mai_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Maithili Computing Research Center, Pune, India rajeshkajha@yahoo.com,akhilesh.k@samusng.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'],
- 'months_short' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'],
- 'weekdays' => ['रविदिन', 'सोमदिन', 'मंगलदिन', 'बुधदिन', 'बृहस्पतीदिन', 'शुक्रदिन', 'शनीदिन'],
- 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'],
- 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-
- 'year' => ':count ऋतु', // less reliable
- 'y' => ':count ऋतु', // less reliable
- 'a_year' => ':count ऋतु', // less reliable
-
- 'month' => ':count महिना',
- 'm' => ':count महिना',
- 'a_month' => ':count महिना',
-
- 'week' => ':count श्रेणी:क्यालेन्डर', // less reliable
- 'w' => ':count श्रेणी:क्यालेन्डर', // less reliable
- 'a_week' => ':count श्रेणी:क्यालेन्डर', // less reliable
-
- 'day' => ':count दिन',
- 'd' => ':count दिन',
- 'a_day' => ':count दिन',
-
- 'hour' => ':count घण्टा',
- 'h' => ':count घण्टा',
- 'a_hour' => ':count घण्टा',
-
- 'minute' => ':count समय', // less reliable
- 'min' => ':count समय', // less reliable
- 'a_minute' => ':count समय', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Ɛnkakɛnyá', 'Ɛndámâ'],
- 'weekdays' => ['Jumapílí', 'Jumatátu', 'Jumane', 'Jumatánɔ', 'Alaámisi', 'Jumáa', 'Jumamósi'],
- 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'months' => ['Oladalʉ́', 'Arát', 'Ɔɛnɨ́ɔɨŋɔk', 'Olodoyíóríê inkókúâ', 'Oloilépūnyīē inkókúâ', 'Kújúɔrɔk', 'Mórusásin', 'Ɔlɔ́ɨ́bɔ́rárɛ', 'Kúshîn', 'Olgísan', 'Pʉshʉ́ka', 'Ntʉ́ŋʉ́s'],
- 'months_short' => ['Dal', 'Ará', 'Ɔɛn', 'Doy', 'Lép', 'Rok', 'Sás', 'Bɔ́r', 'Kús', 'Gís', 'Shʉ́', 'Ntʉ́'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count olameyu', // less reliable
- 'y' => ':count olameyu', // less reliable
- 'a_year' => ':count olameyu', // less reliable
-
- 'week' => ':count engolongeare orwiki', // less reliable
- 'w' => ':count engolongeare orwiki', // less reliable
- 'a_week' => ':count engolongeare orwiki', // less reliable
-
- 'hour' => ':count esahabu', // less reliable
- 'h' => ':count esahabu', // less reliable
- 'a_hour' => ':count esahabu', // less reliable
-
- 'second' => ':count are', // less reliable
- 's' => ':count are', // less reliable
- 'a_second' => ':count are', // less reliable
-
- 'month' => ':count olapa',
- 'm' => ':count olapa',
- 'a_month' => ':count olapa',
-
- 'day' => ':count enkolongʼ',
- 'd' => ':count enkolongʼ',
- 'a_day' => ':count enkolongʼ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/mas.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return \Symfony\Component\Translation\PluralizationRules::get($number, 'sr');
-}, 'me');
-
-/*
- * Authors:
- * - Josh Soref
- * - François B
- * - shaishavgandhi05
- * - Serhan Apaydın
- * - JD Isaacks
- * - Milos Sakovic
- */
-return [
- 'year' => ':count godina|:count godine|:count godina',
- 'y' => ':count godina|:count godine|:count godina',
- 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
- 'm' => ':count mjesec|:count mjeseca|:count mjeseci',
- 'week' => ':count nedjelja|:count nedjelje|:count nedjelja',
- 'w' => ':count nedjelja|:count nedjelje|:count nedjelja',
- 'day' => ':count dan|:count dana|:count dana',
- 'd' => ':count dan|:count dana|:count dana',
- 'hour' => ':count sat|:count sata|:count sati',
- 'h' => ':count sat|:count sata|:count sati',
- 'minute' => ':count minut|:count minuta|:count minuta',
- 'min' => ':count minut|:count minuta|:count minuta',
- 'second' => ':count sekund|:count sekunda|:count sekundi',
- 's' => ':count sekund|:count sekunda|:count sekundi',
- 'ago' => 'prije :time',
- 'from_now' => 'za :time',
- 'diff_yesterday' => 'juče',
- 'diff_tomorrow' => 'sjutra',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[danas u] LT',
- 'nextDay' => '[sjutra u] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[u nedjelju u] LT';
- case 3:
- return '[u srijedu u] LT';
- case 6:
- return '[u subotu u] LT';
- default:
- return '[u] dddd [u] LT';
- }
- },
- 'lastDay' => '[juče u] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[prošle nedjelje u] LT';
- case 1:
- return '[prošle nedjelje u] LT';
- case 2:
- return '[prošlog utorka u] LT';
- case 3:
- return '[prošle srijede u] LT';
- case 4:
- return '[prošlog četvrtka u] LT';
- case 5:
- return '[prošlog petka u] LT';
- default:
- return '[prošle subote u] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
- 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],
- 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
- 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
- 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' i '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['RŨ', 'ŨG'],
- 'weekdays' => ['Kiumia', 'Muramuko', 'Wairi', 'Wethatu', 'Wena', 'Wetano', 'Jumamosi'],
- 'weekdays_short' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
- 'weekdays_min' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
- 'months' => ['Januarĩ', 'Feburuarĩ', 'Machi', 'Ĩpurũ', 'Mĩĩ', 'Njuni', 'Njuraĩ', 'Agasti', 'Septemba', 'Oktũba', 'Novemba', 'Dicemba'],
- 'months_short' => ['JAN', 'FEB', 'MAC', 'ĨPU', 'MĨĨ', 'NJU', 'NJR', 'AGA', 'SPT', 'OKT', 'NOV', 'DEC'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count murume', // less reliable
- 'y' => ':count murume', // less reliable
- 'a_year' => ':count murume', // less reliable
-
- 'month' => ':count muchaara', // less reliable
- 'm' => ':count muchaara', // less reliable
- 'a_month' => ':count muchaara', // less reliable
-
- 'minute' => ':count monto', // less reliable
- 'min' => ':count monto', // less reliable
- 'a_minute' => ':count monto', // less reliable
-
- 'second' => ':count gikeno', // less reliable
- 's' => ':count gikeno', // less reliable
- 'a_second' => ':count gikeno', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mfe_MU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['zanvie', 'fevriye', 'mars', 'avril', 'me', 'zin', 'zilye', 'out', 'septam', 'oktob', 'novam', 'desam'],
- 'months_short' => ['zan', 'fev', 'mar', 'avr', 'me', 'zin', 'zil', 'out', 'sep', 'okt', 'nov', 'des'],
- 'weekdays' => ['dimans', 'lindi', 'mardi', 'merkredi', 'zedi', 'vandredi', 'samdi'],
- 'weekdays_short' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
- 'weekdays_min' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
-
- 'year' => ':count banané',
- 'y' => ':count banané',
- 'a_year' => ':count banané',
-
- 'month' => ':count mwa',
- 'm' => ':count mwa',
- 'a_month' => ':count mwa',
-
- 'week' => ':count sémenn',
- 'w' => ':count sémenn',
- 'a_week' => ':count sémenn',
-
- 'day' => ':count zour',
- 'd' => ':count zour',
- 'a_day' => ':count zour',
-
- 'hour' => ':count -er-tan',
- 'h' => ':count -er-tan',
- 'a_hour' => ':count -er-tan',
-
- 'minute' => ':count minitt',
- 'min' => ':count minitt',
- 'a_minute' => ':count minitt',
-
- 'second' => ':count déziém',
- 's' => ':count déziém',
- 'a_second' => ':count déziém',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mg_MG.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - The Debian Project modified by GNU//Linux Malagasy Rado Ramarotafika,Do-Risika RAFIEFERANTSIARONJY rado@linuxmg.org,dourix@free.fr
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Janoary', 'Febroary', 'Martsa', 'Aprily', 'Mey', 'Jona', 'Jolay', 'Aogositra', 'Septambra', 'Oktobra', 'Novambra', 'Desambra'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mey', 'Jon', 'Jol', 'Aog', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['alahady', 'alatsinainy', 'talata', 'alarobia', 'alakamisy', 'zoma', 'sabotsy'],
- 'weekdays_short' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'],
- 'weekdays_min' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'minute' => ':count minitra', // less reliable
- 'min' => ':count minitra', // less reliable
- 'a_minute' => ':count minitra', // less reliable
-
- 'year' => ':count taona',
- 'y' => ':count taona',
- 'a_year' => ':count taona',
-
- 'month' => ':count volana',
- 'm' => ':count volana',
- 'a_month' => ':count volana',
-
- 'week' => ':count herinandro',
- 'w' => ':count herinandro',
- 'a_week' => ':count herinandro',
-
- 'day' => ':count andro',
- 'd' => ':count andro',
- 'a_day' => ':count andro',
-
- 'hour' => ':count ora',
- 'h' => ':count ora',
- 'a_hour' => ':count ora',
-
- 'second' => ':count segondra',
- 's' => ':count segondra',
- 'a_second' => ':count segondra',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['wichishu', 'mchochil’l'],
- 'weekdays' => ['Sabato', 'Jumatatu', 'Jumanne', 'Jumatano', 'Arahamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
- 'months' => ['Mweri wo kwanza', 'Mweri wo unayeli', 'Mweri wo uneraru', 'Mweri wo unecheshe', 'Mweri wo unethanu', 'Mweri wo thanu na mocha', 'Mweri wo saba', 'Mweri wo nane', 'Mweri wo tisa', 'Mweri wo kumi', 'Mweri wo kumi na moja', 'Mweri wo kumi na yel’li'],
- 'months_short' => ['Kwa', 'Una', 'Rar', 'Che', 'Tha', 'Moc', 'Sab', 'Nan', 'Tis', 'Kum', 'Moj', 'Yel'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'],
- 'weekdays_short' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'],
- 'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'],
- 'months' => ['iməg mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'],
- 'months_short' => ['mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'dddd, YYYY MMMM DD HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mhr_RU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - PeshSajSoft Ltd. Vyacheslav Kileev slavakileev@yandex.ru
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY.MM.DD',
- ],
- 'months' => ['Шорыкйол', 'Пургыж', 'Ӱярня', 'Вӱдшор', 'Ага', 'Пеледыш', 'Сӱрем', 'Сорла', 'Идым', 'Шыжа', 'Кылме', 'Теле'],
- 'months_short' => ['Шрк', 'Пгж', 'Ӱрн', 'Вшр', 'Ага', 'Пдш', 'Срм', 'Срл', 'Идм', 'Шыж', 'Клм', 'Тел'],
- 'weekdays' => ['Рушарня', 'Шочмо', 'Кушкыжмо', 'Вӱргече', 'Изарня', 'Кугарня', 'Шуматкече'],
- 'weekdays_short' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'],
- 'weekdays_min' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count идалык',
- 'y' => ':count идалык',
- 'a_year' => ':count идалык',
-
- 'month' => ':count Тылзе',
- 'm' => ':count Тылзе',
- 'a_month' => ':count Тылзе',
-
- 'week' => ':count арня',
- 'w' => ':count арня',
- 'a_week' => ':count арня',
-
- 'day' => ':count кече',
- 'd' => ':count кече',
- 'a_day' => ':count кече',
-
- 'hour' => ':count час',
- 'h' => ':count час',
- 'a_hour' => ':count час',
-
- 'minute' => ':count минут',
- 'min' => ':count минут',
- 'a_minute' => ':count минут',
-
- 'second' => ':count кокымшан',
- 's' => ':count кокымшан',
- 'a_second' => ':count кокымшан',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'mi');
-
-/*
- * Authors:
- * - François B
- * - John Corrigan
- * - François B
- */
-return [
- 'year' => ':count tau',
- 'a_year' => 'he tau|:count tau',
- 'month' => ':count marama',
- 'a_month' => 'he marama|:count marama',
- 'week' => ':count wiki',
- 'a_week' => 'he wiki|:count wiki',
- 'day' => ':count ra',
- 'a_day' => 'he ra|:count ra',
- 'hour' => ':count haora',
- 'a_hour' => 'te haora|:count haora',
- 'minute' => ':count meneti',
- 'a_minute' => 'he meneti|:count meneti',
- 'second' => ':count hēkona',
- 'a_second' => 'te hēkona ruarua|:count hēkona',
- 'ago' => ':time i mua',
- 'from_now' => 'i roto i :time',
- 'diff_yesterday' => 'inanahi',
- 'diff_tomorrow' => 'apopo',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY [i] HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY [i] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[i teie mahana, i] LT',
- 'nextDay' => '[apopo i] LT',
- 'nextWeek' => 'dddd [i] LT',
- 'lastDay' => '[inanahi i] LT',
- 'lastWeek' => 'dddd [whakamutunga i] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberº',
- 'months' => ['Kohi-tāte', 'Hui-tanguru', 'Poutū-te-rangi', 'Paenga-whāwhā', 'Haratua', 'Pipiri', 'Hōngoingoi', 'Here-turi-kōkā', 'Mahuru', 'Whiringa-ā-nuku', 'Whiringa-ā-rangi', 'Hakihea'],
- 'months_short' => ['Kohi', 'Hui', 'Pou', 'Pae', 'Hara', 'Pipi', 'Hōngoi', 'Here', 'Mahu', 'Whi-nu', 'Whi-ra', 'Haki'],
- 'weekdays' => ['Rātapu', 'Mane', 'Tūrei', 'Wenerei', 'Tāite', 'Paraire', 'Hātarei'],
- 'weekdays_short' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'],
- 'weekdays_min' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' me te '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/mi.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/miq_NI.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'],
- 'months_short' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'],
- 'weekdays' => ['sandi', 'mundi', 'tiusdi', 'wensde', 'tausde', 'praidi', 'satadi'],
- 'weekdays_short' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'],
- 'weekdays_min' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 7,
- 'meridiem' => ['VM', 'NM'],
-
- 'month' => ':count kati', // less reliable
- 'm' => ':count kati', // less reliable
- 'a_month' => ':count kati', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mjw_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Jor Teron bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['Arkoi', 'Thangthang', 'There', 'Jangmi', 'Aru', 'Vosik', 'Jakhong', 'Paipai', 'Chiti', 'Phere', 'Phaikuni', 'Matijong'],
- 'months_short' => ['Ark', 'Thang', 'The', 'Jang', 'Aru', 'Vos', 'Jak', 'Pai', 'Chi', 'Phe', 'Phai', 'Mati'],
- 'weekdays' => ['Bhomkuru', 'Urmi', 'Durmi', 'Thelang', 'Theman', 'Bhomta', 'Bhomti'],
- 'weekdays_short' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'],
- 'weekdays_min' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Sashko Todorov
- * - Josh Soref
- * - François B
- * - Serhan Apaydın
- * - Borislav Mickov
- * - JD Isaacks
- * - Tomi Atanasoski
- */
-return [
- 'year' => ':count година|:count години',
- 'a_year' => 'година|:count години',
- 'y' => ':count год.',
- 'month' => ':count месец|:count месеци',
- 'a_month' => 'месец|:count месеци',
- 'm' => ':count месец|:count месеци',
- 'week' => ':count седмица|:count седмици',
- 'a_week' => 'седмица|:count седмици',
- 'w' => ':count седмица|:count седмици',
- 'day' => ':count ден|:count дена',
- 'a_day' => 'ден|:count дена',
- 'd' => ':count ден|:count дена',
- 'hour' => ':count час|:count часа',
- 'a_hour' => 'час|:count часа',
- 'h' => ':count час|:count часа',
- 'minute' => ':count минута|:count минути',
- 'a_minute' => 'минута|:count минути',
- 'min' => ':count мин.',
- 'second' => ':count секунда|:count секунди',
- 'a_second' => 'неколку секунди|:count секунди',
- 's' => ':count сек.',
- 'ago' => 'пред :time',
- 'from_now' => 'после :time',
- 'after' => 'по :time',
- 'before' => 'пред :time',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'D.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Денес во] LT',
- 'nextDay' => '[Утре во] LT',
- 'nextWeek' => '[Во] dddd [во] LT',
- 'lastDay' => '[Вчера во] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- case 3:
- case 6:
- return '[Изминатата] dddd [во] LT';
- default:
- return '[Изминатиот] dddd [во] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- $lastDigit = $number % 10;
- $last2Digits = $number % 100;
- if ($number === 0) {
- return $number.'-ев';
- }
- if ($last2Digits === 0) {
- return $number.'-ен';
- }
- if ($last2Digits > 10 && $last2Digits < 20) {
- return $number.'-ти';
- }
- if ($lastDigit === 1) {
- return $number.'-ви';
- }
- if ($lastDigit === 2) {
- return $number.'-ри';
- }
- if ($lastDigit === 7 || $lastDigit === 8) {
- return $number.'-ми';
- }
-
- return $number.'-ти';
- },
- 'months' => ['јануари', 'февруари', 'март', 'април', 'мај', 'јуни', 'јули', 'август', 'септември', 'октомври', 'ноември', 'декември'],
- 'months_short' => ['јан', 'фев', 'мар', 'апр', 'мај', 'јун', 'јул', 'авг', 'сеп', 'окт', 'ное', 'дек'],
- 'weekdays' => ['недела', 'понеделник', 'вторник', 'среда', 'четврток', 'петок', 'сабота'],
- 'weekdays_short' => ['нед', 'пон', 'вто', 'сре', 'чет', 'пет', 'саб'],
- 'weekdays_min' => ['нe', 'пo', 'вт', 'ср', 'че', 'пе', 'сa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' и '],
- 'meridiem' => ['АМ', 'ПМ'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/mk.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - JD Isaacks
- */
-return [
- 'year' => ':count വർഷം',
- 'a_year' => 'ഒരു വർഷം|:count വർഷം',
- 'month' => ':count മാസം',
- 'a_month' => 'ഒരു മാസം|:count മാസം',
- 'week' => ':count ആഴ്ച',
- 'a_week' => 'ഒരാഴ്ച|:count ആഴ്ച',
- 'day' => ':count ദിവസം',
- 'a_day' => 'ഒരു ദിവസം|:count ദിവസം',
- 'hour' => ':count മണിക്കൂർ',
- 'a_hour' => 'ഒരു മണിക്കൂർ|:count മണിക്കൂർ',
- 'minute' => ':count മിനിറ്റ്',
- 'a_minute' => 'ഒരു മിനിറ്റ്|:count മിനിറ്റ്',
- 'second' => ':count സെക്കൻഡ്',
- 'a_second' => 'അൽപ നിമിഷങ്ങൾ|:count സെക്കൻഡ്',
- 'ago' => ':time മുൻപ്',
- 'from_now' => ':time കഴിഞ്ഞ്',
- 'diff_yesterday' => 'ഇന്നലെ',
- 'diff_tomorrow' => 'നാളെ',
- 'formats' => [
- 'LT' => 'A h:mm -നു',
- 'LTS' => 'A h:mm:ss -നു',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm -നു',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm -നു',
- ],
- 'calendar' => [
- 'sameDay' => '[ഇന്ന്] LT',
- 'nextDay' => '[നാളെ] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[ഇന്നലെ] LT',
- 'lastWeek' => '[കഴിഞ്ഞ] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'രാത്രി';
- }
- if ($hour < 12) {
- return 'രാവിലെ';
- }
- if ($hour < 17) {
- return 'ഉച്ച കഴിഞ്ഞ്';
- }
- if ($hour < 20) {
- return 'വൈകുന്നേരം';
- }
-
- return 'രാത്രി';
- },
- 'months' => ['ജനുവരി', 'ഫെബ്രുവരി', 'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗസ്റ്റ്', 'സെപ്റ്റംബർ', 'ഒക്ടോബർ', 'നവംബർ', 'ഡിസംബർ'],
- 'months_short' => ['ജനു.', 'ഫെബ്രു.', 'മാർ.', 'ഏപ്രി.', 'മേയ്', 'ജൂൺ', 'ജൂലൈ.', 'ഓഗ.', 'സെപ്റ്റ.', 'ഒക്ടോ.', 'നവം.', 'ഡിസം.'],
- 'weekdays' => ['ഞായറാഴ്ച', 'തിങ്കളാഴ്ച', 'ചൊവ്വാഴ്ച', 'ബുധനാഴ്ച', 'വ്യാഴാഴ്ച', 'വെള്ളിയാഴ്ച', 'ശനിയാഴ്ച'],
- 'weekdays_short' => ['ഞായർ', 'തിങ്കൾ', 'ചൊവ്വ', 'ബുധൻ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
- 'weekdays_min' => ['ഞാ', 'തി', 'ചൊ', 'ബു', 'വ്യാ', 'വെ', 'ശ'],
- 'list' => ', ',
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ml.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @translator Batmandakh Erdenebileg <batmandakh.e@icloud.com>
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - tjku
- * - Max Melentiev
- * - Zolzaya Erdenebaatar
- * - Tom Hughes
- * - Akira Matsuda
- * - Christopher Dell
- * - Michael Kessler
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Nicolás Hock Isaza
- * - Ochirkhuyag
- * - Batmandakh
- */
-return [
- 'year' => ':count жил',
- 'y' => ':count жил',
- 'month' => ':count сар',
- 'm' => ':count сар',
- 'week' => ':count долоо хоног',
- 'w' => ':count долоо хоног',
- 'day' => ':count өдөр',
- 'd' => ':count өдөр',
- 'hour' => ':count цаг',
- 'h' => ':countц',
- 'minute' => ':count минут',
- 'min' => ':countм',
- 'second' => ':count секунд',
- 's' => ':countс',
-
- 'ago' => ':timeн өмнө',
- 'year_ago' => ':count жилий',
- 'month_ago' => ':count сары',
- 'day_ago' => ':count хоногий',
- 'hour_ago' => ':count цагий',
- 'minute_ago' => ':count минуты',
- 'second_ago' => ':count секунды',
-
- 'from_now' => 'одоогоос :time',
- 'year_from_now' => ':count жилийн дараа',
- 'month_from_now' => ':count сарын дараа',
- 'day_from_now' => ':count хоногийн дараа',
- 'hour_from_now' => ':count цагийн дараа',
- 'minute_from_now' => ':count минутын дараа',
- 'second_from_now' => ':count секундын дараа',
-
- // Does it required to make translation for before, after as follows? hmm, I think we've made it with ago and from now keywords already. Anyway, I've included it just in case of undesired action...
- 'after' => ':timeн дараа',
- 'year_after' => ':count жилий',
- 'month_after' => ':count сары',
- 'day_after' => ':count хоногий',
- 'hour_after' => ':count цагий',
- 'minute_after' => ':count минуты',
- 'second_after' => ':count секунды',
- 'before' => ':timeн өмнө',
- 'year_before' => ':count жилий',
- 'month_before' => ':count сары',
- 'day_before' => ':count хоногий',
- 'hour_before' => ':count цагий',
- 'minute_before' => ':count минуты',
- 'second_before' => ':count секунды',
- 'list' => ', ',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'YYYY MMMM DD',
- 'LLL' => 'YY-MM-DD, HH:mm',
- 'LLLL' => 'YYYY MMMM DD, HH:mm',
- ],
- 'weekdays' => ['Ням', 'Даваа', 'Мягмар', 'Лхагва', 'Пүрэв', 'Баасан', 'Бямба'],
- 'weekdays_short' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
- 'weekdays_min' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
- 'months' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'],
- 'months_short' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'],
- 'meridiem' => ['өглөө', 'орой'],
- 'first_day_of_week' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/mn.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/mni_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat Pune libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['জানুৱারি', 'ফেব্রুৱারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'সেপ্তেম্বর', 'ওক্তোবর', 'নবেম্বর', 'ডিসেম্বর'],
- 'months_short' => ['জান', 'ফেব', 'মার', 'এপ্রি', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ', 'ওক্ত', 'নবে', 'ডিস'],
- 'weekdays' => ['নোংমাইজিং', 'নিংথৌকাবা', 'লৈবাকপোকপা', 'য়ুমশকৈশা', 'শগোলশেন', 'ইরাই', 'থাংজ'],
- 'weekdays_short' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'],
- 'weekdays_min' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['এ.ম.', 'প.ম.'],
-
- 'year' => ':count ইসিং', // less reliable
- 'y' => ':count ইসিং', // less reliable
- 'a_year' => ':count ইসিং', // less reliable
-
- 'second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
- 's' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
- 'a_second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ro.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return [
- 'year' => ':count वर्ष',
- 'y' => ':count वर्ष',
- 'month' => ':count महिना|:count महिने',
- 'm' => ':count महिना|:count महिने',
- 'week' => ':count आठवडा|:count आठवडे',
- 'w' => ':count आठवडा|:count आठवडे',
- 'day' => ':count दिवस',
- 'd' => ':count दिवस',
- 'hour' => ':count तास',
- 'h' => ':count तास',
- 'minute' => ':count मिनिटे',
- 'min' => ':count मिनिटे',
- 'second' => ':count सेकंद',
- 's' => ':count सेकंद',
-
- 'ago' => ':timeपूर्वी',
- 'from_now' => ':timeमध्ये',
-
- 'diff_yesterday' => 'काल',
- 'diff_tomorrow' => 'उद्या',
-
- 'formats' => [
- 'LT' => 'A h:mm वाजता',
- 'LTS' => 'A h:mm:ss वाजता',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm वाजता',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm वाजता',
- ],
-
- 'calendar' => [
- 'sameDay' => '[आज] LT',
- 'nextDay' => '[उद्या] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[काल] LT',
- 'lastWeek' => '[मागील] dddd, LT',
- 'sameElse' => 'L',
- ],
-
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'रात्री';
- }
- if ($hour < 10) {
- return 'सकाळी';
- }
- if ($hour < 17) {
- return 'दुपारी';
- }
- if ($hour < 20) {
- return 'सायंकाळी';
- }
-
- return 'रात्री';
- },
-
- 'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ऑगस्ट', 'सप्टेंबर', 'ऑक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
- 'months_short' => ['जाने.', 'फेब्रु.', 'मार्च.', 'एप्रि.', 'मे.', 'जून.', 'जुलै.', 'ऑग.', 'सप्टें.', 'ऑक्टो.', 'नोव्हें.', 'डिसें.'],
- 'weekdays' => ['रविवार', 'सोमवार', 'मंगळवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],
- 'weekdays_short' => ['रवि', 'सोम', 'मंगळ', 'बुध', 'गुरू', 'शुक्र', 'शनि'],
- 'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],
- 'list' => [', ', ' आणि '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/mr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Azri Jamil
- * - JD Isaacks
- * - Josh Soref
- * - Azri Jamil
- * - Hariadi Hinta
- */
-return [
- 'year' => '{1}setahun|]1,Inf[:count tahun',
- 'y' => ':count tahun',
- 'month' => '{1}sebulan|]1,Inf[:count bulan',
- 'm' => ':count bulan',
- 'week' => '{1}seminggu|]1,Inf[:count minggu',
- 'w' => ':count minggu',
- 'day' => '{1}sehari|]1,Inf[:count hari',
- 'd' => ':count hari',
- 'hour' => '{1}sejam|]1,Inf[:count jam',
- 'h' => ':count jam',
- 'minute' => '{1}seminit|]1,Inf[:count minit',
- 'min' => ':count minit',
- 'second' => '{1}beberapa saat|]1,Inf[:count saat',
- 's' => ':count saat',
- 'ago' => ':time yang lepas',
- 'from_now' => 'dalam :time',
- 'after' => ':time selepas',
- 'before' => ':time sebelum',
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm.ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY [pukul] HH.mm',
- 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Hari ini pukul] LT',
- 'nextDay' => '[Esok pukul] LT',
- 'nextWeek' => 'dddd [pukul] LT',
- 'lastDay' => '[Kelmarin pukul] LT',
- 'lastWeek' => 'dddd [lepas pukul] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 11) {
- return 'pagi';
- }
- if ($hour < 15) {
- return 'tengahari';
- }
- if ($hour < 19) {
- return 'petang';
- }
-
- return 'malam';
- },
- 'months' => ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogs', 'Sep', 'Okt', 'Nov', 'Dis'],
- 'weekdays' => ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],
- 'weekdays_short' => ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
- 'weekdays_min' => ['Ah', 'Is', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' dan '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ms.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/MM/yy',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY, h:mm a',
- 'LLLL' => 'dd MMMM YYYY, h:mm a',
- ],
- 'meridiem' => ['a', 'p'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Azri Jamil
- * - JD Isaacks
- */
-return require __DIR__.'/ms.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ms.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/MM/yy',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY, h:mm a',
- 'LLLL' => 'dddd, D MMMM YYYY, h:mm a',
- ],
- 'meridiem' => ['a', 'p'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Alessandro Maruccia
- */
-return [
- 'year' => 'sena|:count sni|:count sni|:count sni',
- 'y' => 'sa sena|:count snin|:count snin|:count snin',
- 'month' => 'xahar|:count xhur|:count xhur|:count xhur',
- 'm' => ':count xahar|:count xhur|:count xhur|:count xhur',
- 'week' => 'gimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat',
- 'w' => 'ġimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat',
- 'day' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet',
- 'd' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet',
- 'hour' => 'siegħa|:count siegħat|:count siegħat|:count siegħat',
- 'h' => 'siegħa|:count sigħat|:count sigħat|:count sigħat',
- 'minute' => 'minuta|:count minuti|:count minuti|:count minuti',
- 'min' => 'min.|:count min.|:count min.|:count min.',
- 'second' => 'ftit sekondi|:count sekondi|:count sekondi|:count sekondi',
- 's' => 'sek.|:count sek.|:count sek.|:count sek.',
- 'ago' => ':time ilu',
- 'from_now' => 'f’ :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Illum fil-]LT',
- 'nextDay' => '[Għada fil-]LT',
- 'nextWeek' => 'dddd [fil-]LT',
- 'lastDay' => '[Il-bieraħ fil-]LT',
- 'lastWeek' => 'dddd [li għadda] [fil-]LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberº',
- 'months' => ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju', 'Lulju', 'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
- 'months_short' => ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul', 'Aww', 'Set', 'Ott', 'Nov', 'Diċ'],
- 'weekdays' => ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa', 'Il-Ħamis', 'Il-Ġimgħa', 'Is-Sibt'],
- 'weekdays_short' => ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
- 'weekdays_min' => ['Ħa', 'Tn', 'Tl', 'Er', 'Ħa', 'Ġi', 'Si'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' u '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/mt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['comme', 'lilli'],
- 'weekdays' => ['Com’yakke', 'Comlaaɗii', 'Comzyiiɗii', 'Comkolle', 'Comkaldǝɓlii', 'Comgaisuu', 'Comzyeɓsuu'],
- 'weekdays_short' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
- 'weekdays_min' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
- 'months' => ['Fĩi Loo', 'Cokcwaklaŋne', 'Cokcwaklii', 'Fĩi Marfoo', 'Madǝǝuutǝbijaŋ', 'Mamǝŋgwãafahbii', 'Mamǝŋgwãalii', 'Madǝmbii', 'Fĩi Dǝɓlii', 'Fĩi Mundaŋ', 'Fĩi Gwahlle', 'Fĩi Yuru'],
- 'months_short' => ['FLO', 'CLA', 'CKI', 'FMF', 'MAD', 'MBI', 'MLI', 'MAM', 'FDE', 'FMU', 'FGW', 'FYU'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'my');
-
-/*
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- * - Nay Lin Aung
- */
-return [
- 'year' => 'တစ်နှစ်|:count နှစ်',
- 'y' => ':count နှစ်',
- 'month' => 'တစ်လ|:count လ',
- 'm' => ':count လ',
- 'week' => ':count ပတ်',
- 'w' => ':count ပတ်',
- 'day' => 'တစ်ရက်|:count ရက်',
- 'd' => ':count ရက်',
- 'hour' => 'တစ်နာရီ|:count နာရီ',
- 'h' => ':count နာရီ',
- 'minute' => 'တစ်မိနစ်|:count မိနစ်',
- 'min' => ':count မိနစ်',
- 'second' => 'စက္ကန်.အနည်းငယ်|:count စက္ကန့်',
- 's' => ':count စက္ကန့်',
- 'ago' => 'လွန်ခဲ့သော :time က',
- 'from_now' => 'လာမည့် :time မှာ',
- 'after' => ':time ကြာပြီးနောက်',
- 'before' => ':time မတိုင်ခင်',
- 'diff_now' => 'အခုလေးတင်',
- 'diff_yesterday' => 'မနေ့က',
- 'diff_tomorrow' => 'မနက်ဖြန်',
- 'diff_before_yesterday' => 'တမြန်နေ့က',
- 'diff_after_tomorrow' => 'တဘက်ခါ',
- 'period_recurrences' => ':count ကြိမ်',
- 'formats' => [
- 'LT' => 'Oh:Om A',
- 'LTS' => 'Oh:Om:Os A',
- 'L' => 'OD/OM/OY',
- 'LL' => 'OD MMMM OY',
- 'LLL' => 'OD MMMM OY Oh:Om A',
- 'LLLL' => 'dddd OD MMMM OY Oh:Om A',
- ],
- 'calendar' => [
- 'sameDay' => '[ယနေ.] LT [မှာ]',
- 'nextDay' => '[မနက်ဖြန်] LT [မှာ]',
- 'nextWeek' => 'dddd LT [မှာ]',
- 'lastDay' => '[မနေ.က] LT [မှာ]',
- 'lastWeek' => '[ပြီးခဲ့သော] dddd LT [မှာ]',
- 'sameElse' => 'L',
- ],
- 'months' => ['ဇန်နဝါရီ', 'ဖေဖော်ဝါရီ', 'မတ်', 'ဧပြီ', 'မေ', 'ဇွန်', 'ဇူလိုင်', 'သြဂုတ်', 'စက်တင်ဘာ', 'အောက်တိုဘာ', 'နိုဝင်ဘာ', 'ဒီဇင်ဘာ'],
- 'months_short' => ['ဇန်', 'ဖေ', 'မတ်', 'ပြီ', 'မေ', 'ဇွန်', 'လိုင်', 'သြ', 'စက်', 'အောက်', 'နို', 'ဒီ'],
- 'weekdays' => ['တနင်္ဂနွေ', 'တနင်္လာ', 'အင်္ဂါ', 'ဗုဒ္ဓဟူး', 'ကြာသပတေး', 'သောကြာ', 'စနေ'],
- 'weekdays_short' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'],
- 'weekdays_min' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'alt_numbers' => ['၀၀', '၀၁', '၀၂', '၀၃', '၀၄', '၀၅', '၀၆', '၀၇', '၀၈', '၀၉', '၁၀', '၁၁', '၁၂', '၁၃', '၁၄', '၁၅', '၁၆', '၁၇', '၁၈', '၁၉', '၂၀', '၂၁', '၂၂', '၂၃', '၂၄', '၂၅', '၂၆', '၂၇', '၂၈', '၂၉', '၃၀', '၃၁', '၃၂', '၃၃', '၃၄', '၃၅', '၃၆', '၃၇', '၃၈', '၃၉', '၄၀', '၄၁', '၄၂', '၄၃', '၄၄', '၄၅', '၄၆', '၄၇', '၄၈', '၄၉', '၅၀', '၅၁', '၅၂', '၅၃', '၅၄', '၅၅', '၅၆', '၅၇', '၅၈', '၅၉', '၆၀', '၆၁', '၆၂', '၆၃', '၆၄', '၆၅', '၆၆', '၆၇', '၆၈', '၆၉', '၇၀', '၇၁', '၇၂', '၇၃', '၇၄', '၇၅', '၇၆', '၇၇', '၇၈', '၇၉', '၈၀', '၈၁', '၈၂', '၈၃', '၈၄', '၈၅', '၈၆', '၈၇', '၈၈', '၈၉', '၉၀', '၉၁', '၉၂', '၉၃', '၉၄', '၉၅', '၉၆', '၉၇', '၉၈', '၉၉'],
- 'meridiem' => ['နံနက်', 'ညနေ'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/my.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fa.php', [
- 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
- 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
- 'first_day_of_week' => 6,
- 'weekend' => [5, 5],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/nan_TW.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY年MM月DD日',
- ],
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
- 'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'],
- 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['頂晡', '下晡'],
-
- 'year' => ':count 年',
- 'y' => ':count 年',
- 'a_year' => ':count 年',
-
- 'month' => ':count goe̍h',
- 'm' => ':count goe̍h',
- 'a_month' => ':count goe̍h',
-
- 'week' => ':count lé-pài',
- 'w' => ':count lé-pài',
- 'a_week' => ':count lé-pài',
-
- 'day' => ':count 日',
- 'd' => ':count 日',
- 'a_day' => ':count 日',
-
- 'hour' => ':count tiám-cheng',
- 'h' => ':count tiám-cheng',
- 'a_hour' => ':count tiám-cheng',
-
- 'minute' => ':count Hun-cheng',
- 'min' => ':count Hun-cheng',
- 'a_minute' => ':count Hun-cheng',
-
- 'second' => ':count Bió',
- 's' => ':count Bió',
- 'a_second' => ':count Bió',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Arne Goetje arne@canonical.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
- 'months' => ['1goe̍h', '2goe̍h', '3goe̍h', '4goe̍h', '5goe̍h', '6goe̍h', '7goe̍h', '8goe̍h', '9goe̍h', '10goe̍h', '11goe̍h', '12goe̍h'],
- 'months_short' => ['1g', '2g', '3g', '4g', '5g', '6g', '7g', '8g', '9g', '10g', '11g', '12g'],
- 'weekdays' => ['lé-pài-ji̍t', 'pài-it', 'pài-jī', 'pài-saⁿ', 'pài-sì', 'pài-gō͘', 'pài-la̍k'],
- 'weekdays_short' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'],
- 'weekdays_min' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['téng-po͘', 'ē-po͘'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['ǁgoagas', 'ǃuias'],
- 'weekdays' => ['Sontaxtsees', 'Mantaxtsees', 'Denstaxtsees', 'Wunstaxtsees', 'Dondertaxtsees', 'Fraitaxtsees', 'Satertaxtsees'],
- 'weekdays_short' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
- 'weekdays_min' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
- 'months' => ['ǃKhanni', 'ǃKhanǀgôab', 'ǀKhuuǁkhâb', 'ǃHôaǂkhaib', 'ǃKhaitsâb', 'Gamaǀaeb', 'ǂKhoesaob', 'Aoǁkhuumûǁkhâb', 'Taraǀkhuumûǁkhâb', 'ǂNûǁnâiseb', 'ǀHooǂgaeb', 'Hôasoreǁkhâb'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
- ],
-
- 'year' => ':count kurigu',
- 'y' => ':count kurigu',
- 'a_year' => ':count kurigu',
-
- 'month' => ':count ǁaub', // less reliable
- 'm' => ':count ǁaub', // less reliable
- 'a_month' => ':count ǁaub', // less reliable
-
- 'week' => ':count hû', // less reliable
- 'w' => ':count hû', // less reliable
- 'a_week' => ':count hû', // less reliable
-
- 'day' => ':count ǀhobas', // less reliable
- 'd' => ':count ǀhobas', // less reliable
- 'a_day' => ':count ǀhobas', // less reliable
-
- 'hour' => ':count ǂgaes', // less reliable
- 'h' => ':count ǂgaes', // less reliable
- 'a_hour' => ':count ǂgaes', // less reliable
-
- 'minute' => ':count minutga', // less reliable
- 'min' => ':count minutga', // less reliable
- 'a_minute' => ':count minutga', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Alexander Tømmerås
- * - Sigurd Gartmann
- * - JD Isaacks
- */
-return [
- 'year' => ':count år|:count år',
- 'a_year' => 'ett år|:count år',
- 'y' => ':count år|:count år',
- 'month' => ':count måned|:count måneder',
- 'a_month' => 'en måned|:count måneder',
- 'm' => ':count md.',
- 'week' => ':count uke|:count uker',
- 'a_week' => 'en uke|:count uker',
- 'w' => ':count u.',
- 'day' => ':count dag|:count dager',
- 'a_day' => 'en dag|:count dager',
- 'd' => ':count d.',
- 'hour' => ':count time|:count timer',
- 'a_hour' => 'en time|:count timer',
- 'h' => ':count t',
- 'minute' => ':count minutt|:count minutter',
- 'a_minute' => 'ett minutt|:count minutter',
- 'min' => ':count min',
- 'second' => ':count sekund|:count sekunder',
- 'a_second' => 'noen sekunder|:count sekunder',
- 's' => ':count sek',
- 'ago' => ':time siden',
- 'from_now' => 'om :time',
- 'after' => ':time etter',
- 'before' => ':time før',
- 'diff_now' => 'akkurat nå',
- 'diff_yesterday' => 'i går',
- 'diff_tomorrow' => 'i morgen',
- 'diff_before_yesterday' => 'i forgårs',
- 'diff_after_tomorrow' => 'i overmorgen',
- 'period_recurrences' => 'en gang|:count ganger',
- 'period_interval' => 'hver :interval',
- 'period_start_date' => 'fra :date',
- 'period_end_date' => 'til :date',
- 'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
- 'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
- 'weekdays_short' => ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
- 'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
- 'ordinal' => ':number.',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY [kl.] HH:mm',
- 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[i dag kl.] LT',
- 'nextDay' => '[i morgen kl.] LT',
- 'nextWeek' => 'dddd [kl.] LT',
- 'lastDay' => '[i går kl.] LT',
- 'lastWeek' => '[forrige] dddd [kl.] LT',
- 'sameElse' => 'L',
- ],
- 'list' => [', ', ' og '],
- 'meridiem' => ['a.m.', 'p.m.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/nb.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/nb.php', [
- 'formats' => [
- 'LL' => 'D. MMM YYYY',
- 'LLL' => 'D. MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd D. MMMM YYYY, HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Sonto', 'Mvulo', 'Sibili', 'Sithathu', 'Sine', 'Sihlanu', 'Mgqibelo'],
- 'weekdays_short' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
- 'weekdays_min' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
- 'months' => ['Zibandlela', 'Nhlolanja', 'Mbimbitho', 'Mabasa', 'Nkwenkwezi', 'Nhlangula', 'Ntulikazi', 'Ncwabakazi', 'Mpandula', 'Mfumfu', 'Lwezi', 'Mpalakazi'],
- 'months_short' => ['Zib', 'Nhlo', 'Mbi', 'Mab', 'Nkw', 'Nhla', 'Ntu', 'Ncw', 'Mpan', 'Mfu', 'Lwe', 'Mpal'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-
- 'year' => 'okweminyaka engu-:count', // less reliable
- 'y' => 'okweminyaka engu-:count', // less reliable
- 'a_year' => 'okweminyaka engu-:count', // less reliable
-
- 'month' => 'inyanga ezingu-:count',
- 'm' => 'inyanga ezingu-:count',
- 'a_month' => 'inyanga ezingu-:count',
-
- 'week' => 'amaviki angu-:count',
- 'w' => 'amaviki angu-:count',
- 'a_week' => 'amaviki angu-:count',
-
- 'day' => 'kwamalanga angu-:count',
- 'd' => 'kwamalanga angu-:count',
- 'a_day' => 'kwamalanga angu-:count',
-
- 'hour' => 'amahola angu-:count',
- 'h' => 'amahola angu-:count',
- 'a_hour' => 'amahola angu-:count',
-
- 'minute' => 'imizuzu engu-:count',
- 'min' => 'imizuzu engu-:count',
- 'a_minute' => 'imizuzu engu-:count',
-
- 'second' => 'imizuzwana engu-:count',
- 's' => 'imizuzwana engu-:count',
- 'a_second' => 'imizuzwana engu-:count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/nds_DE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Jannuaar', 'Feberwaar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
- 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
- 'weekdays' => ['Sünndag', 'Maandag', 'Dingsdag', 'Middeweek', 'Dunnersdag', 'Freedag', 'Sünnavend'],
- 'weekdays_short' => ['Sdag', 'Maan', 'Ding', 'Migg', 'Dunn', 'Free', 'Svd.'],
- 'weekdays_min' => ['Sdag', 'Maan', 'Ding', 'Migg', 'Dunn', 'Free', 'Svd.'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count Johr',
- 'y' => ':count Johr',
- 'a_year' => ':count Johr',
-
- 'month' => ':count Maand',
- 'm' => ':count Maand',
- 'a_month' => ':count Maand',
-
- 'week' => ':count Week',
- 'w' => ':count Week',
- 'a_week' => ':count Week',
-
- 'day' => ':count Dag',
- 'd' => ':count Dag',
- 'a_day' => ':count Dag',
-
- 'hour' => ':count Stünn',
- 'h' => ':count Stünn',
- 'a_hour' => ':count Stünn',
-
- 'minute' => ':count Minuut',
- 'min' => ':count Minuut',
- 'a_minute' => ':count Minuut',
-
- 'second' => ':count sekunn',
- 's' => ':count sekunn',
- 'a_second' => ':count sekunn',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'],
- 'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'],
- 'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'],
- 'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
- 'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - nootanghimire
- * - Josh Soref
- * - Nj Subedi
- * - JD Isaacks
- */
-return [
- 'year' => 'एक बर्ष|:count बर्ष',
- 'y' => ':count वर्ष',
- 'month' => 'एक महिना|:count महिना',
- 'm' => ':count महिना',
- 'week' => ':count हप्ता',
- 'w' => ':count हप्ता',
- 'day' => 'एक दिन|:count दिन',
- 'd' => ':count दिन',
- 'hour' => 'एक घण्टा|:count घण्टा',
- 'h' => ':count घण्टा',
- 'minute' => 'एक मिनेट|:count मिनेट',
- 'min' => ':count मिनेट',
- 'second' => 'केही क्षण|:count सेकेण्ड',
- 's' => ':count सेकेण्ड',
- 'ago' => ':time अगाडि',
- 'from_now' => ':timeमा',
- 'after' => ':time पछि',
- 'before' => ':time अघि',
- 'diff_yesterday' => 'हिजो',
- 'diff_tomorrow' => 'भोलि',
- 'formats' => [
- 'LT' => 'Aको h:mm बजे',
- 'LTS' => 'Aको h:mm:ss बजे',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, Aको h:mm बजे',
- 'LLLL' => 'dddd, D MMMM YYYY, Aको h:mm बजे',
- ],
- 'calendar' => [
- 'sameDay' => '[आज] LT',
- 'nextDay' => '[भोलि] LT',
- 'nextWeek' => '[आउँदो] dddd[,] LT',
- 'lastDay' => '[हिजो] LT',
- 'lastWeek' => '[गएको] dddd[,] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 3) {
- return 'राति';
- }
- if ($hour < 12) {
- return 'बिहान';
- }
- if ($hour < 16) {
- return 'दिउँसो';
- }
- if ($hour < 20) {
- return 'साँझ';
- }
-
- return 'राति';
- },
- 'months' => ['जनवरी', 'फेब्रुवरी', 'मार्च', 'अप्रिल', 'मई', 'जुन', 'जुलाई', 'अगष्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
- 'months_short' => ['जन.', 'फेब्रु.', 'मार्च', 'अप्रि.', 'मई', 'जुन', 'जुलाई.', 'अग.', 'सेप्ट.', 'अक्टो.', 'नोभे.', 'डिसे.'],
- 'weekdays' => ['आइतबार', 'सोमबार', 'मङ्गलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'],
- 'weekdays_short' => ['आइत.', 'सोम.', 'मङ्गल.', 'बुध.', 'बिहि.', 'शुक्र.', 'शनि.'],
- 'weekdays_min' => ['आ.', 'सो.', 'मं.', 'बु.', 'बि.', 'शु.', 'श.'],
- 'list' => [', ', ' र '],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ne.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'yy/M/d',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D, h:mm a',
- 'LLLL' => 'YYYY MMMM D, dddd, h:mm a',
- ],
- 'months' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
- 'months_short' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
- 'weekend' => [0, 0],
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ne.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/nhn_MX.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
- 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
- 'weekdays' => ['teoilhuitl', 'ceilhuitl', 'omeilhuitl', 'yeilhuitl', 'nahuilhuitl', 'macuililhuitl', 'chicuaceilhuitl'],
- 'weekdays_short' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'],
- 'weekdays_min' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'],
- 'day_of_first_week_of_year' => 1,
-
- 'month' => ':count metztli', // less reliable
- 'm' => ':count metztli', // less reliable
- 'a_month' => ':count metztli', // less reliable
-
- 'week' => ':count tonalli', // less reliable
- 'w' => ':count tonalli', // less reliable
- 'a_week' => ':count tonalli', // less reliable
-
- 'day' => ':count tonatih', // less reliable
- 'd' => ':count tonatih', // less reliable
- 'a_day' => ':count tonatih', // less reliable
-
- 'minute' => ':count toltecayotl', // less reliable
- 'min' => ':count toltecayotl', // less reliable
- 'a_minute' => ':count toltecayotl', // less reliable
-
- 'second' => ':count ome', // less reliable
- 's' => ':count ome', // less reliable
- 'a_second' => ':count ome', // less reliable
-
- 'year' => ':count xihuitl',
- 'y' => ':count xihuitl',
- 'a_year' => ':count xihuitl',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/niu_NU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RockET Systems Emani Fakaotimanava-Lui emani@niue.nu
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Ianuali', 'Fepuali', 'Masi', 'Apelila', 'Me', 'Iuni', 'Iulai', 'Aokuso', 'Sepetema', 'Oketopa', 'Novema', 'Tesemo'],
- 'months_short' => ['Ian', 'Fep', 'Mas', 'Ape', 'Me', 'Iun', 'Iul', 'Aok', 'Sep', 'Oke', 'Nov', 'Tes'],
- 'weekdays' => ['Aho Tapu', 'Aho Gofua', 'Aho Ua', 'Aho Lotu', 'Aho Tuloto', 'Aho Falaile', 'Aho Faiumu'],
- 'weekdays_short' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'],
- 'weekdays_min' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count tau',
- 'y' => ':count tau',
- 'a_year' => ':count tau',
-
- 'month' => ':count mahina',
- 'm' => ':count mahina',
- 'a_month' => ':count mahina',
-
- 'week' => ':count faahi tapu',
- 'w' => ':count faahi tapu',
- 'a_week' => ':count faahi tapu',
-
- 'day' => ':count aho',
- 'd' => ':count aho',
- 'a_day' => ':count aho',
-
- 'hour' => ':count e tulā',
- 'h' => ':count e tulā',
- 'a_hour' => ':count e tulā',
-
- 'minute' => ':count minuti',
- 'min' => ':count minuti',
- 'a_minute' => ':count minuti',
-
- 'second' => ':count sekone',
- 's' => ':count sekone',
- 'a_second' => ':count sekone',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Roy
- * - Stephan
- * - François B
- * - Tim Fish
- * - Kevin Huang
- * - Jacob Middag
- * - JD Isaacks
- * - Roy
- * - Stephan
- * - François B
- * - Tim Fish
- * - Jacob Middag
- * - JD Isaacks
- * - Propaganistas
- * - MegaXLR
- * - adriaanzon
- * - MonkeyPhysics
- * - JeroenG
- * - RikSomers
- * - proclame
- * - Rik de Groot (hwdegroot)
- */
-return [
- 'year' => ':count jaar|:count jaar',
- 'a_year' => 'een jaar|:count jaar',
- 'y' => ':countj',
- 'month' => ':count maand|:count maanden',
- 'a_month' => 'een maand|:count maanden',
- 'm' => ':countmnd',
- 'week' => ':count week|:count weken',
- 'a_week' => 'een week|:count weken',
- 'w' => ':countw',
- 'day' => ':count dag|:count dagen',
- 'a_day' => 'een dag|:count dagen',
- 'd' => ':countd',
- 'hour' => ':count uur|:count uur',
- 'a_hour' => 'een uur|:count uur',
- 'h' => ':countu',
- 'minute' => ':count minuut|:count minuten',
- 'a_minute' => 'een minuut|:count minuten',
- 'min' => ':countmin',
- 'second' => ':count seconde|:count seconden',
- 'a_second' => 'een paar seconden|:count seconden',
- 's' => ':counts',
- 'ago' => ':time geleden',
- 'from_now' => 'over :time',
- 'after' => ':time later',
- 'before' => ':time eerder',
- 'diff_now' => 'nu',
- 'diff_yesterday' => 'gisteren',
- 'diff_tomorrow' => 'morgen',
- 'diff_after_tomorrow' => 'overmorgen',
- 'diff_before_yesterday' => 'eergisteren',
- 'period_recurrences' => ':count keer',
- 'period_interval' => function ($interval) {
- /** @var string $output */
- $output = preg_replace('/^(een|één|1)\s+/', '', $interval);
-
- if (preg_match('/^(een|één|1)( jaar|j| uur|u)/', $interval)) {
- return "elk $output";
- }
-
- return "elke $output";
- },
- 'period_start_date' => 'van :date',
- 'period_end_date' => 'tot :date',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD-MM-YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[vandaag om] LT',
- 'nextDay' => '[morgen om] LT',
- 'nextWeek' => 'dddd [om] LT',
- 'lastDay' => '[gisteren om] LT',
- 'lastWeek' => '[afgelopen] dddd [om] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
- },
- 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
- 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'mmm_suffix' => '.',
- 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
- 'weekdays_short' => ['zo.', 'ma.', 'di.', 'wo.', 'do.', 'vr.', 'za.'],
- 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' en '],
- 'meridiem' => ['\'s ochtends', '\'s middags'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/nl.php', [
- 'formats' => [
- 'L' => 'DD-MM-YY',
- ],
- 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
- 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
- 'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Roy
- * - Stephan
- * - François B
- * - Tim Fish
- * - Kevin Huang
- * - Jacob Middag
- * - JD Isaacks
- * - Propaganistas
- */
-return array_replace_recursive(require __DIR__.'/nl.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/nl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/nl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/nl.php', [
- 'formats' => [
- 'L' => 'DD-MM-YY',
- ],
- 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
- 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
- 'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/nl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/nl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['maná', 'kugú'],
- 'weekdays' => ['sɔ́ndɔ', 'mɔ́ndɔ', 'sɔ́ndɔ mafú mába', 'sɔ́ndɔ mafú málal', 'sɔ́ndɔ mafú mána', 'mabágá má sukul', 'sásadi'],
- 'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
- 'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
- 'months' => ['ngwɛn matáhra', 'ngwɛn ńmba', 'ngwɛn ńlal', 'ngwɛn ńna', 'ngwɛn ńtan', 'ngwɛn ńtuó', 'ngwɛn hɛmbuɛrí', 'ngwɛn lɔmbi', 'ngwɛn rɛbvuâ', 'ngwɛn wum', 'ngwɛn wum navǔr', 'krísimin'],
- 'months_short' => ['ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6', 'ng7', 'ng8', 'ng9', 'ng10', 'ng11', 'kris'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Alexander Tømmerås
- * - Øystein
- * - JD Isaacks
- */
-return [
- 'year' => ':count år|:count år',
- 'a_year' => 'eit år|:count år',
- 'month' => ':count månad|:count månader',
- 'a_month' => 'ein månad|:count månader',
- 'week' => ':count uke|:count uker',
- 'a_week' => 'eit uke|:count uker',
- 'day' => ':count dag|:count dagar',
- 'a_day' => 'ein dag|:count dagar',
- 'hour' => ':count time|:count timar',
- 'a_hour' => 'ein time|:count timar',
- 'minute' => ':count minutt',
- 'a_minute' => 'eit minutt|:count minutt',
- 'second' => ':count sekund',
- 'a_second' => 'nokre sekund|:count sekund',
- 'ago' => ':time sidan',
- 'from_now' => 'om :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY [kl.] H:mm',
- 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[I dag klokka] LT',
- 'nextDay' => '[I morgon klokka] LT',
- 'nextWeek' => 'dddd [klokka] LT',
- 'lastDay' => '[I går klokka] LT',
- 'lastWeek' => '[Føregåande] dddd [klokka] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
- 'weekdays' => ['sundag', 'måndag', 'tysdag', 'onsdag', 'torsdag', 'fredag', 'laurdag'],
- 'weekdays_short' => ['sun', 'mån', 'tys', 'ons', 'tor', 'fre', 'lau'],
- 'weekdays_min' => ['su', 'må', 'ty', 'on', 'to', 'fr', 'la'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' og '],
- 'meridiem' => ['f.m.', 'e.m.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/nn.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['mbaʼámbaʼ', 'ncwònzém'],
- 'weekdays' => null,
- 'weekdays_short' => ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ', 'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ', 'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ', 'màga lyɛ̌ʼ'],
- 'weekdays_min' => null,
- 'months' => null,
- 'months_short' => ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ', 'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ', 'saŋ tyɛ̀b tyɛ̀b mbʉ̀ŋ', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ', 'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/yy',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => '[lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm',
- 'LLLL' => 'dddd , [lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Daniel S. Billing
- * - Paul
- * - Jimmie Johansson
- * - Jens Herlevsen
- */
-return array_replace_recursive(require __DIR__.'/nb.php', [
- 'formats' => [
- 'LLL' => 'D. MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY [kl.] HH:mm',
- ],
- 'calendar' => [
- 'nextWeek' => 'på dddd [kl.] LT',
- 'lastWeek' => '[i] dddd[s kl.] LT',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/nr_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Janabari', 'uFeberbari', 'uMatjhi', 'u-Apreli', 'Meyi', 'Juni', 'Julayi', 'Arhostosi', 'Septemba', 'Oktoba', 'Usinyikhaba', 'Disemba'],
- 'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mey', 'Jun', 'Jul', 'Arh', 'Sep', 'Okt', 'Usi', 'Dis'],
- 'weekdays' => ['uSonto', 'uMvulo', 'uLesibili', 'lesithathu', 'uLesine', 'ngoLesihlanu', 'umGqibelo'],
- 'weekdays_short' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
- 'weekdays_min' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/nso_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Janaware', 'Febereware', 'Matšhe', 'Aprele', 'Mei', 'June', 'Julae', 'Agostose', 'Setemere', 'Oktobere', 'Nofemere', 'Disemere'],
- 'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Set', 'Okt', 'Nof', 'Dis'],
- 'weekdays' => ['LaMorena', 'Mošupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Mokibelo'],
- 'weekdays_short' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
- 'weekdays_min' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count ngwaga',
- 'y' => ':count ngwaga',
- 'a_year' => ':count ngwaga',
-
- 'month' => ':count Kgwedi',
- 'm' => ':count Kgwedi',
- 'a_month' => ':count Kgwedi',
-
- 'week' => ':count Beke',
- 'w' => ':count Beke',
- 'a_week' => ':count Beke',
-
- 'day' => ':count Letšatši',
- 'd' => ':count Letšatši',
- 'a_day' => ':count Letšatši',
-
- 'hour' => ':count Iri',
- 'h' => ':count Iri',
- 'a_hour' => ':count Iri',
-
- 'minute' => ':count Motsotso',
- 'min' => ':count Motsotso',
- 'a_minute' => ':count Motsotso',
-
- 'second' => ':count motsotswana',
- 's' => ':count motsotswana',
- 'a_second' => ':count motsotswana',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['RW', 'TŊ'],
- 'weekdays' => ['Cäŋ kuɔth', 'Jiec la̱t', 'Rɛw lätni', 'Diɔ̱k lätni', 'Ŋuaan lätni', 'Dhieec lätni', 'Bäkɛl lätni'],
- 'weekdays_short' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'],
- 'weekdays_min' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'],
- 'months' => ['Tiop thar pɛt', 'Pɛt', 'Duɔ̱ɔ̱ŋ', 'Guak', 'Duät', 'Kornyoot', 'Pay yie̱tni', 'Tho̱o̱r', 'Tɛɛr', 'Laath', 'Kur', 'Tio̱p in di̱i̱t'],
- 'months_short' => ['Tiop', 'Pɛt', 'Duɔ̱ɔ̱', 'Guak', 'Duä', 'Kor', 'Pay', 'Thoo', 'Tɛɛ', 'Laa', 'Kur', 'Tid'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd D MMMM YYYY h:mm a',
- ],
-
- 'year' => ':count jiök', // less reliable
- 'y' => ':count jiök', // less reliable
- 'a_year' => ':count jiök', // less reliable
-
- 'month' => ':count pay', // less reliable
- 'm' => ':count pay', // less reliable
- 'a_month' => ':count pay', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'],
- 'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
- 'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
- 'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
- 'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Quentí
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number == 1 ? 0 : 1;
-}, 'oc');
-
-return [
- 'year' => ':count an|:count ans',
- 'a_year' => 'un an|:count ans',
- 'y' => ':count an|:count ans',
- 'month' => ':count mes|:count meses',
- 'a_month' => 'un mes|:count meses',
- 'm' => ':count mes|:count meses',
- 'week' => ':count setmana|:count setmanas',
- 'a_week' => 'una setmana|:count setmanas',
- 'w' => ':count setmana|:count setmanas',
- 'day' => ':count jorn|:count jorns',
- 'a_day' => 'un jorn|:count jorns',
- 'd' => ':count jorn|:count jorns',
- 'hour' => ':count ora|:count oras',
- 'a_hour' => 'una ora|:count oras',
- 'h' => ':count ora|:count oras',
- 'minute' => ':count minuta|:count minutas',
- 'a_minute' => 'una minuta|:count minutas',
- 'min' => ':count minuta|:count minutas',
- 'second' => ':count segonda|:count segondas',
- 'a_second' => 'una segonda|:count segondas',
- 's' => ':count segonda|:count segondas',
- 'ago' => 'fa :time',
- 'from_now' => 'd\'aquí :time',
- 'after' => ':time aprèp',
- 'before' => ':time abans',
- 'diff_now' => 'ara meteis',
- 'diff_yesterday' => 'ièr',
- 'diff_tomorrow' => 'deman',
- 'diff_before_yesterday' => 'ièr delà',
- 'diff_after_tomorrow' => 'deman passat',
- 'period_recurrences' => ':count còp|:count còps',
- 'period_interval' => 'cada :interval',
- 'period_start_date' => 'de :date',
- 'period_end_date' => 'fins a :date',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM [de] YYYY',
- 'LLL' => 'D MMMM [de] YYYY [a] H:mm',
- 'LLLL' => 'dddd D MMMM [de] YYYY [a] H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Uèi a] LT',
- 'nextDay' => '[Deman a] LT',
- 'nextWeek' => 'dddd [a] LT',
- 'lastDay' => '[Ièr a] LT',
- 'lastWeek' => 'dddd [passat a] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['de genièr', 'de febrièr', 'de març', 'd\'abrial', 'de mai', 'de junh', 'de julhet', 'd\'agost', 'de setembre', 'd’octòbre', 'de novembre', 'de decembre'],
- 'months_standalone' => ['genièr', 'febrièr', 'març', 'abrial', 'mai', 'junh', 'julh', 'agost', 'setembre', 'octòbre', 'novembre', 'decembre'],
- 'months_short' => ['gen.', 'feb.', 'març', 'abr.', 'mai', 'junh', 'julh', 'ago.', 'sep.', 'oct.', 'nov.', 'dec.'],
- 'weekdays' => ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'],
- 'weekdays_short' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
- 'weekdays_min' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
- 'ordinal' => function ($number, $period) {
- return $number.(
- ($period === 'w' || $period === 'W') ? 'a' : (
- ($number === 1) ? 'r' : (
- ($number === 2) ? 'n' : (
- ($number === 3) ? 'r' : (
- ($number === 4) ? 't' : 'è'
- )
- )
- )
- )
- );
- },
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' e '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/oc.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation & Sagalee Oromoo Publishing Co. Inc. locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'dd-MMM-YYYY',
- 'LLL' => 'dd MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, MMMM D, YYYY HH:mm',
- ],
- 'months' => ['Amajjii', 'Guraandhala', 'Bitooteessa', 'Elba', 'Caamsa', 'Waxabajjii', 'Adooleessa', 'Hagayya', 'Fuulbana', 'Onkololeessa', 'Sadaasa', 'Muddee'],
- 'months_short' => ['Ama', 'Gur', 'Bit', 'Elb', 'Cam', 'Wax', 'Ado', 'Hag', 'Ful', 'Onk', 'Sad', 'Mud'],
- 'weekdays' => ['Dilbata', 'Wiixata', 'Qibxata', 'Roobii', 'Kamiisa', 'Jimaata', 'Sanbata'],
- 'weekdays_short' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
- 'weekdays_min' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['WD', 'WB'],
-
- 'year' => 'wggoota :count',
- 'y' => 'wggoota :count',
- 'a_year' => 'wggoota :count',
-
- 'month' => 'ji’a :count',
- 'm' => 'ji’a :count',
- 'a_month' => 'ji’a :count',
-
- 'week' => 'torban :count',
- 'w' => 'torban :count',
- 'a_week' => 'torban :count',
-
- 'day' => 'guyyaa :count',
- 'd' => 'guyyaa :count',
- 'a_day' => 'guyyaa :count',
-
- 'hour' => 'saʼaatii :count',
- 'h' => 'saʼaatii :count',
- 'a_hour' => 'saʼaatii :count',
-
- 'minute' => 'daqiiqaa :count',
- 'min' => 'daqiiqaa :count',
- 'a_minute' => 'daqiiqaa :count',
-
- 'second' => 'sekoondii :count',
- 's' => 'sekoondii :count',
- 'a_second' => 'sekoondii :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/om.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/om.php', [
- 'day_of_first_week_of_year' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/or_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM AP Linux Technology Center, Yamato Software Laboratory bug-glibc@gnu.org
- */
-return [
- 'formats' => [
- 'LT' => 'Oh:Om A',
- 'LTS' => 'Oh:Om:Os A',
- 'L' => 'OD-OM-OY',
- 'LL' => 'OD MMMM OY',
- 'LLL' => 'OD MMMM OY Oh:Om A',
- 'LLLL' => 'dddd OD MMMM OY Oh:Om A',
- ],
- 'months' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'],
- 'months_short' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'],
- 'weekdays' => ['ରବିବାର', 'ସୋମବାର', 'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର', 'ଶୁକ୍ରବାର', 'ଶନିବାର'],
- 'weekdays_short' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
- 'weekdays_min' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
- 'day_of_first_week_of_year' => 1,
- 'alt_numbers' => ['୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯', '୧୦', '୧୧', '୧୨', '୧୩', '୧୪', '୧୫', '୧୬', '୧୭', '୧୮', '୧୯', '୨୦', '୨୧', '୨୨', '୨୩', '୨୪', '୨୫', '୨୬', '୨୭', '୨୮', '୨୯', '୩୦', '୩୧', '୩୨', '୩୩', '୩୪', '୩୫', '୩୬', '୩୭', '୩୮', '୩୯', '୪୦', '୪୧', '୪୨', '୪୩', '୪୪', '୪୫', '୪୬', '୪୭', '୪୮', '୪୯', '୫୦', '୫୧', '୫୨', '୫୩', '୫୪', '୫୫', '୫୬', '୫୭', '୫୮', '୫୯', '୬୦', '୬୧', '୬୨', '୬୩', '୬୪', '୬୫', '୬୬', '୬୭', '୬୮', '୬୯', '୭୦', '୭୧', '୭୨', '୭୩', '୭୪', '୭୫', '୭୬', '୭୭', '୭୮', '୭୯', '୮୦', '୮୧', '୮୨', '୮୩', '୮୪', '୮୫', '୮୬', '୮୭', '୮୮', '୮୯', '୯୦', '୯୧', '୯୨', '୯୩', '୯୪', '୯୫', '୯୬', '୯୭', '୯୮', '୯୯'],
- 'year' => ':count ବର୍ଷ',
- 'y' => ':count ବ.',
- 'month' => ':count ମାସ',
- 'm' => ':count ମା.',
- 'week' => ':count ସପ୍ତାହ',
- 'w' => ':count ସପ୍ତା.',
- 'day' => ':count ଦିନ',
- 'd' => ':count ଦିନ',
- 'hour' => ':count ଘଣ୍ତ',
- 'h' => ':count ଘ.',
- 'minute' => ':count ମିନଟ',
- 'min' => ':count ମି.',
- 'second' => ':count ସେକଣ୍ଢ',
- 's' => ':count ସେ.',
- 'ago' => ':time ପୂର୍ବେ',
- 'from_now' => ':timeରେ',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/os_RU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['январы', 'февралы', 'мартъийы', 'апрелы', 'майы', 'июны', 'июлы', 'августы', 'сентябры', 'октябры', 'ноябры', 'декабры'],
- 'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
- 'weekdays' => ['Хуыцаубон', 'Къуырисæр', 'Дыццæг', 'Æртыццæг', 'Цыппæрæм', 'Майрæмбон', 'Сабат'],
- 'weekdays_short' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'],
- 'weekdays_min' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'minute' => ':count гыццыл', // less reliable
- 'min' => ':count гыццыл', // less reliable
- 'a_minute' => ':count гыццыл', // less reliable
-
- 'second' => ':count æндæр', // less reliable
- 's' => ':count æндæр', // less reliable
- 'a_second' => ':count æндæр', // less reliable
-
- 'year' => ':count аз',
- 'y' => ':count аз',
- 'a_year' => ':count аз',
-
- 'month' => ':count мӕй',
- 'm' => ':count мӕй',
- 'a_month' => ':count мӕй',
-
- 'week' => ':count къуыри',
- 'w' => ':count къуыри',
- 'a_week' => ':count къуыри',
-
- 'day' => ':count бон',
- 'd' => ':count бон',
- 'a_day' => ':count бон',
-
- 'hour' => ':count сахат',
- 'h' => ':count сахат',
- 'a_hour' => ':count сахат',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - Punjab
- */
-return [
- 'year' => 'ਇੱਕ ਸਾਲ|:count ਸਾਲ',
- 'month' => 'ਇੱਕ ਮਹੀਨਾ|:count ਮਹੀਨੇ',
- 'week' => 'ਹਫਤਾ|:count ਹਫ਼ਤੇ',
- 'day' => 'ਇੱਕ ਦਿਨ|:count ਦਿਨ',
- 'hour' => 'ਇੱਕ ਘੰਟਾ|:count ਘੰਟੇ',
- 'minute' => 'ਇਕ ਮਿੰਟ|:count ਮਿੰਟ',
- 'second' => 'ਕੁਝ ਸਕਿੰਟ|:count ਸਕਿੰਟ',
- 'ago' => ':time ਪਿਛਲੇ',
- 'from_now' => ':time ਵਿੱਚ',
- 'diff_yesterday' => 'ਕਲ',
- 'diff_tomorrow' => 'ਕਲ',
- 'formats' => [
- 'LT' => 'A h:mm ਵਜੇ',
- 'LTS' => 'A h:mm:ss ਵਜੇ',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm ਵਜੇ',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm ਵਜੇ',
- ],
- 'calendar' => [
- 'sameDay' => '[ਅਜ] LT',
- 'nextDay' => '[ਕਲ] LT',
- 'nextWeek' => '[ਅਗਲਾ] dddd, LT',
- 'lastDay' => '[ਕਲ] LT',
- 'lastWeek' => '[ਪਿਛਲੇ] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'ਰਾਤ';
- }
- if ($hour < 10) {
- return 'ਸਵੇਰ';
- }
- if ($hour < 17) {
- return 'ਦੁਪਹਿਰ';
- }
- if ($hour < 20) {
- return 'ਸ਼ਾਮ';
- }
-
- return 'ਰਾਤ';
- },
- 'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
- 'months_short' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
- 'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨੀਚਰਵਾਰ'],
- 'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'],
- 'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' ਅਤੇ '],
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ur.php', [
- 'weekdays' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
- 'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
- 'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
- 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd, DD MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/pa.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D/M/yy',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY, h:mm a',
- 'LLLL' => 'dddd, D MMMM YYYY, h:mm a',
- ],
- 'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
- 'months_short' => ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ', 'ਸਤੰ', 'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
- 'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
- 'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
- 'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕ', 'ਸ਼ਨਿੱ'],
- 'weekend' => [0, 0],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Guo Xiang Tan
- * - Josh Soref
- * - Ash
- * - harpreetkhalsagtbit
- */
-return require __DIR__.'/pa.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'],
- 'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
- 'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
- 'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ص', 'ش'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return [
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm:ss',
- 'L' => 'DD-MM-YY',
- 'LL' => 'MMMM [di] DD, YYYY',
- 'LLL' => 'DD MMM HH.mm',
- 'LLLL' => 'MMMM DD, YYYY HH.mm',
- ],
- 'months' => ['yanüari', 'febrüari', 'mart', 'aprel', 'mei', 'yüni', 'yüli', 'ougùstùs', 'sèptèmber', 'oktober', 'novèmber', 'desèmber'],
- 'months_short' => ['yan', 'feb', 'mar', 'apr', 'mei', 'yün', 'yül', 'oug', 'sèp', 'okt', 'nov', 'des'],
- 'weekdays' => ['djadomingo', 'djaluna', 'djamars', 'djawebs', 'djarason', 'djabierne', 'djasabra'],
- 'weekdays_short' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'],
- 'weekdays_min' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'year' => ':count aña',
- 'month' => ':count luna',
- 'week' => ':count siman',
- 'day' => ':count dia',
- 'hour' => ':count ora',
- 'minute' => ':count minüt',
- 'second' => ':count sekònde',
- 'list' => [', ', ' i '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com
- */
-return require __DIR__.'/pap.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com
- */
-return require __DIR__.'/pap.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Wacław Jacek
- * - François B
- * - Tim Fish
- * - Serhan Apaydın
- * - Massimiliano Caniparoli
- * - JD Isaacks
- * - Jakub Szwacz
- * - Jan
- * - Paul
- * - damlys
- * - Marek (marast78)
- * - Peter (UnrulyNatives)
- */
-return [
- 'year' => ':count rok|:count lata|:count lat',
- 'y' => ':countr|:countl',
- 'month' => ':count miesiąc|:count miesiące|:count miesięcy',
- 'm' => ':countmies',
- 'week' => ':count tydzień|:count tygodnie|:count tygodni',
- 'w' => ':counttyg',
- 'day' => ':count dzień|:count dni|:count dni',
- 'd' => ':countd',
- 'hour' => ':count godzina|:count godziny|:count godzin',
- 'h' => ':countg',
- 'minute' => ':count minuta|:count minuty|:count minut',
- 'min' => ':countm',
- 'second' => ':count sekunda|:count sekundy|:count sekund',
- 'a_second' => '{1}kilka sekund|:count sekunda|:count sekundy|:count sekund',
- 's' => ':counts',
- 'ago' => ':time temu',
- 'from_now' => 'za :time',
- 'after' => ':time po',
- 'before' => ':time przed',
- 'diff_now' => 'przed chwilą',
- 'diff_yesterday' => 'wczoraj',
- 'diff_tomorrow' => 'jutro',
- 'diff_before_yesterday' => 'przedwczoraj',
- 'diff_after_tomorrow' => 'pojutrze',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Dziś o] LT',
- 'nextDay' => '[Jutro o] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[W niedzielę o] LT';
- case 2:
- return '[We wtorek o] LT';
- case 3:
- return '[W środę o] LT';
- case 6:
- return '[W sobotę o] LT';
- default:
- return '[W] dddd [o] LT';
- }
- },
- 'lastDay' => '[Wczoraj o] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[W zeszłą niedzielę o] LT';
- case 3:
- return '[W zeszłą środę o] LT';
- case 6:
- return '[W zeszłą sobotę o] LT';
- default:
- return '[W zeszły] dddd [o] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca', 'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia'],
- 'months_standalone' => ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień'],
- 'months_short' => ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru'],
- 'months_regexp' => '/DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota'],
- 'weekdays_short' => ['ndz', 'pon', 'wt', 'śr', 'czw', 'pt', 'sob'],
- 'weekdays_min' => ['Nd', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' i '],
- 'meridiem' => ['przed południem', 'po południu'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
- 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
- ],
-
- 'year' => ':count meta',
- 'y' => ':count meta',
- 'a_year' => ':count meta',
-
- 'month' => ':count mēniks', // less reliable
- 'm' => ':count mēniks', // less reliable
- 'a_month' => ':count mēniks', // less reliable
-
- 'week' => ':count sawaītin', // less reliable
- 'w' => ':count sawaītin', // less reliable
- 'a_week' => ':count sawaītin', // less reliable
-
- 'day' => ':count di',
- 'd' => ':count di',
- 'a_day' => ':count di',
-
- 'hour' => ':count bruktēt', // less reliable
- 'h' => ':count bruktēt', // less reliable
- 'a_hour' => ':count bruktēt', // less reliable
-
- 'minute' => ':count līkuts', // less reliable
- 'min' => ':count līkuts', // less reliable
- 'a_minute' => ':count līkuts', // less reliable
-
- 'second' => ':count kitan', // less reliable
- 's' => ':count kitan', // less reliable
- 'a_second' => ':count kitan', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Muhammad Nasir Rahimi
- */
-return [
- 'year' => ':count کال|:count کاله',
- 'y' => ':countکال|:countکاله',
- 'month' => ':count مياشت|:count مياشتي',
- 'm' => ':countمياشت|:countمياشتي',
- 'week' => ':count اونۍ|:count اونۍ',
- 'w' => ':countاونۍ|:countاونۍ',
- 'day' => ':count ورځ|:count ورځي',
- 'd' => ':countورځ|:countورځي',
- 'hour' => ':count ساعت|:count ساعته',
- 'h' => ':countساعت|:countساعته',
- 'minute' => ':count دقيقه|:count دقيقې',
- 'min' => ':countدقيقه|:countدقيقې',
- 'second' => ':count ثانيه|:count ثانيې',
- 's' => ':countثانيه|:countثانيې',
- 'ago' => ':time دمخه',
- 'from_now' => ':time له اوس څخه',
- 'after' => ':time وروسته',
- 'before' => ':time دمخه',
- 'list' => ['، ', ' او '],
- 'meridiem' => ['غ.م.', 'غ.و.'],
- 'weekdays' => ['يونۍ', 'دونۍ', 'درېنۍ', 'څلرنۍ', 'پينځنۍ', 'جمعه', 'اونۍ'],
- 'weekdays_short' => ['يونۍ', 'دونۍ', 'درېنۍ', 'څلرنۍ', 'پينځنۍ', 'جمعه', 'اونۍ'],
- 'weekdays_min' => ['يونۍ', 'دونۍ', 'درېنۍ', 'څلرنۍ', 'پينځنۍ', 'جمعه', 'اونۍ'],
- 'months' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_standalone' => ['جنوري', 'فېبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_short_standalone' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'first_day_of_week' => 6,
- 'weekend' => [4, 5],
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'YYYY/M/d',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'د YYYY د MMMM D H:mm',
- 'LLLL' => 'dddd د YYYY د MMMM D H:mm',
- ],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ps.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Cassiano Montanari
- * - Matt Pope
- * - François B
- * - Prodis
- * - JD Isaacks
- * - Raphael Amorim
- * - João Magalhães
- * - victortobias
- * - Paulo Freitas
- * - Sebastian Thierer
- * - Claudson Martins (claudsonm)
- */
-return [
- 'year' => ':count ano|:count anos',
- 'a_year' => 'um ano|:count anos',
- 'y' => ':counta',
- 'month' => ':count mês|:count meses',
- 'a_month' => 'um mês|:count meses',
- 'm' => ':countm',
- 'week' => ':count semana|:count semanas',
- 'a_week' => 'uma semana|:count semanas',
- 'w' => ':countsem',
- 'day' => ':count dia|:count dias',
- 'a_day' => 'um dia|:count dias',
- 'd' => ':countd',
- 'hour' => ':count hora|:count horas',
- 'a_hour' => 'uma hora|:count horas',
- 'h' => ':counth',
- 'minute' => ':count minuto|:count minutos',
- 'a_minute' => 'um minuto|:count minutos',
- 'min' => ':countmin',
- 'second' => ':count segundo|:count segundos',
- 'a_second' => 'alguns segundos|:count segundos',
- 's' => ':counts',
- 'ago' => 'há :time',
- 'from_now' => 'em :time',
- 'after' => ':time depois',
- 'before' => ':time antes',
- 'diff_now' => 'agora',
- 'diff_yesterday' => 'ontem',
- 'diff_tomorrow' => 'amanhã',
- 'diff_before_yesterday' => 'anteontem',
- 'diff_after_tomorrow' => 'depois de amanhã',
- 'period_recurrences' => 'uma vez|:count vezes',
- 'period_interval' => 'cada :interval',
- 'period_start_date' => 'de :date',
- 'period_end_date' => 'até :date',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D [de] MMMM [de] YYYY',
- 'LLL' => 'D [de] MMMM [de] YYYY HH:mm',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Hoje às] LT',
- 'nextDay' => '[Amanhã às] LT',
- 'nextWeek' => 'dddd [às] LT',
- 'lastDay' => '[Ontem às] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- case 6:
- return '[Último] dddd [às] LT';
- default:
- return '[Última] dddd [às] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberº',
- 'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
- 'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'],
- 'weekdays' => ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
- 'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
- 'weekdays_min' => ['Do', '2ª', '3ª', '4ª', '5ª', '6ª', 'Sá'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' e '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Cassiano Montanari
- * - Eduardo Dalla Vecchia
- * - David Rodrigues
- * - Matt Pope
- * - François B
- * - Prodis
- * - Marlon Maxwel
- * - JD Isaacks
- * - Raphael Amorim
- * - Rafael Raupp
- * - felipeleite1
- * - swalker
- * - Lucas Macedo
- * - Paulo Freitas
- * - Sebastian Thierer
- */
-return array_replace_recursive(require __DIR__.'/pt.php', [
- 'period_recurrences' => 'uma|:count vez',
- 'period_interval' => 'toda :interval',
- 'formats' => [
- 'LLL' => 'D [de] MMMM [de] YYYY [às] HH:mm',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY [às] HH:mm',
- ],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/pt.php', [
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'LLL' => 'D [de] MMMM [de] YYYY, h:mm a',
- 'LLLL' => 'dddd, D [de] MMMM [de] YYYY, h:mm a',
- ],
- 'first_day_of_week' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/pt.php', [
- 'first_day_of_week' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RAP bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/pt.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
- 'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'],
- 'weekdays' => ['domingo', 'segunda', 'terça', 'quarta', 'quinta', 'sexta', 'sábado'],
- 'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
- 'weekdays_min' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/pt.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/es_UY.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM, YYYY HH:mm',
- ],
- 'first_day_of_week' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/qu.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/qu.php', [
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/quz_PE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['iniru', 'phiwriru', 'marsu', 'awril', 'mayu', 'huniyu', 'huliyu', 'agustu', 'siptiyimri', 'uktuwri', 'nuwiyimri', 'tisiyimri'],
- 'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'hun', 'hul', 'agu', 'sip', 'ukt', 'nuw', 'tis'],
- 'weekdays' => ['tuminku', 'lunis', 'martis', 'miyirkulis', 'juywis', 'wiyirnis', 'sawatu'],
- 'weekdays_short' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'],
- 'weekdays_min' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'],
- 'day_of_first_week_of_year' => 1,
-
- 'minute' => ':count uchuy', // less reliable
- 'min' => ':count uchuy', // less reliable
- 'a_minute' => ':count uchuy', // less reliable
-
- 'year' => ':count wata',
- 'y' => ':count wata',
- 'a_year' => ':count wata',
-
- 'month' => ':count killa',
- 'm' => ':count killa',
- 'a_month' => ':count killa',
-
- 'week' => ':count simana',
- 'w' => ':count simana',
- 'a_week' => ':count simana',
-
- 'day' => ':count pʼunchaw',
- 'd' => ':count pʼunchaw',
- 'a_day' => ':count pʼunchaw',
-
- 'hour' => ':count ura',
- 'h' => ':count ura',
- 'a_hour' => ':count ura',
-
- 'second' => ':count iskay ñiqin',
- 's' => ':count iskay ñiqin',
- 'a_second' => ':count iskay ñiqin',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/raj_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - meghrajsuthar03@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'],
- 'months_short' => ['जन', 'फर', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुल', 'अग', 'सित', 'अक्टू', 'नव', 'दिस'],
- 'weekdays' => ['रविवार', 'सोमवार', 'मंगल्लवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'],
- 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
- 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-
- 'year' => ':count आंहू', // less reliable
- 'y' => ':count आंहू', // less reliable
- 'a_year' => ':count आंहू', // less reliable
-
- 'month' => ':count सूरज', // less reliable
- 'm' => ':count सूरज', // less reliable
- 'a_month' => ':count सूरज', // less reliable
-
- 'week' => ':count निवाज', // less reliable
- 'w' => ':count निवाज', // less reliable
- 'a_week' => ':count निवाज', // less reliable
-
- 'day' => ':count अेक', // less reliable
- 'd' => ':count अेक', // less reliable
- 'a_day' => ':count अेक', // less reliable
-
- 'hour' => ':count दुनियांण', // less reliable
- 'h' => ':count दुनियांण', // less reliable
- 'a_hour' => ':count दुनियांण', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - tjku
- * - Max Melentiev
- * - Juanito Fatas
- * - Tsutomu Kuroda
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Nicolás Hock Isaza
- * - sebastian de castelberg
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'Do MMMM YYYY',
- 'LLL' => 'Do MMMM, HH:mm [Uhr]',
- 'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]',
- ],
- 'year' => ':count onn|:count onns',
- 'month' => ':count mais',
- 'week' => ':count emna|:count emnas',
- 'day' => ':count di|:count dis',
- 'hour' => ':count oura|:count ouras',
- 'minute' => ':count minuta|:count minutas',
- 'second' => ':count secunda|:count secundas',
- 'weekdays' => ['dumengia', 'glindesdi', 'mardi', 'mesemna', 'gievgia', 'venderdi', 'sonda'],
- 'weekdays_short' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
- 'weekdays_min' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
- 'months' => ['schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur', 'fanadur', 'avust', 'settember', 'october', 'november', 'december'],
- 'months_short' => ['schan', 'favr', 'mars', 'avr', 'matg', 'zercl', 'fan', 'avust', 'sett', 'oct', 'nov', 'dec'],
- 'meridiem' => ['avantmezdi', 'suentermezdi'],
- 'list' => [', ', ' e '],
- 'first_day_of_week' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Z.MU.', 'Z.MW.'],
- 'weekdays' => ['Ku w’indwi', 'Ku wa mbere', 'Ku wa kabiri', 'Ku wa gatatu', 'Ku wa kane', 'Ku wa gatanu', 'Ku wa gatandatu'],
- 'weekdays_short' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
- 'weekdays_min' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
- 'months' => ['Nzero', 'Ruhuhuma', 'Ntwarante', 'Ndamukiza', 'Rusama', 'Ruheshi', 'Mukakaro', 'Nyandagaro', 'Nyakanga', 'Gitugutu', 'Munyonyo', 'Kigarama'],
- 'months_short' => ['Mut.', 'Gas.', 'Wer.', 'Mat.', 'Gic.', 'Kam.', 'Nya.', 'Kan.', 'Nze.', 'Ukw.', 'Ugu.', 'Uku.'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'year' => 'imyaka :count',
- 'y' => 'imyaka :count',
- 'a_year' => 'imyaka :count',
-
- 'month' => 'amezi :count',
- 'm' => 'amezi :count',
- 'a_month' => 'amezi :count',
-
- 'week' => 'indwi :count',
- 'w' => 'indwi :count',
- 'a_week' => 'indwi :count',
-
- 'day' => 'imisi :count',
- 'd' => 'imisi :count',
- 'a_day' => 'imisi :count',
-
- 'hour' => 'amasaha :count',
- 'h' => 'amasaha :count',
- 'a_hour' => 'amasaha :count',
-
- 'minute' => 'iminuta :count',
- 'min' => 'iminuta :count',
- 'a_minute' => 'iminuta :count',
-
- 'second' => 'inguvu :count', // less reliable
- 's' => 'inguvu :count', // less reliable
- 'a_second' => 'inguvu :count', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- * - Cătălin Georgescu
- * - Valentin Ivaşcu (oriceon)
- */
-return [
- 'year' => ':count an|:count ani|:count ani',
- 'a_year' => 'un an|:count ani|:count ani',
- 'y' => ':count a.',
- 'month' => ':count lună|:count luni|:count luni',
- 'a_month' => 'o lună|:count luni|:count luni',
- 'm' => ':count l.',
- 'week' => ':count săptămână|:count săptămâni|:count săptămâni',
- 'a_week' => 'o săptămână|:count săptămâni|:count săptămâni',
- 'w' => ':count săp.',
- 'day' => ':count zi|:count zile|:count zile',
- 'a_day' => 'o zi|:count zile|:count zile',
- 'd' => ':count z.',
- 'hour' => ':count oră|:count ore|:count ore',
- 'a_hour' => 'o oră|:count ore|:count ore',
- 'h' => ':count o.',
- 'minute' => ':count minut|:count minute|:count minute',
- 'a_minute' => 'un minut|:count minute|:count minute',
- 'min' => ':count m.',
- 'second' => ':count secundă|:count secunde|:count secunde',
- 'a_second' => 'câteva secunde|:count secunde|:count secunde',
- 's' => ':count sec.',
- 'ago' => ':time în urmă',
- 'from_now' => 'peste :time',
- 'after' => 'peste :time',
- 'before' => 'acum :time',
- 'diff_yesterday' => 'ieri',
- 'diff_tomorrow' => 'mâine',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[azi la] LT',
- 'nextDay' => '[mâine la] LT',
- 'nextWeek' => 'dddd [la] LT',
- 'lastDay' => '[ieri la] LT',
- 'lastWeek' => '[fosta] dddd [la] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],
- 'months_short' => ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.', 'sept.', 'oct.', 'nov.', 'dec.'],
- 'weekdays' => ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri', 'sâmbătă'],
- 'weekdays_short' => ['dum', 'lun', 'mar', 'mie', 'joi', 'vin', 'sâm'],
- 'weekdays_min' => ['du', 'lu', 'ma', 'mi', 'jo', 'vi', 'sâ'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' și '],
- 'meridiem' => ['a.m.', 'p.m.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ro.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ro.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['kang’ama', 'kingoto'],
- 'weekdays' => ['Ijumapili', 'Ijumatatu', 'Ijumanne', 'Ijumatano', 'Alhamisi', 'Ijumaa', 'Ijumamosi'],
- 'weekdays_short' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
- 'weekdays_min' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
- 'months' => ['Mweri wa kwanza', 'Mweri wa kaili', 'Mweri wa katatu', 'Mweri wa kaana', 'Mweri wa tanu', 'Mweri wa sita', 'Mweri wa saba', 'Mweri wa nane', 'Mweri wa tisa', 'Mweri wa ikumi', 'Mweri wa ikumi na moja', 'Mweri wa ikumi na mbili'],
- 'months_short' => ['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Bari Badamshin
- * - Jørn Ølmheim
- * - François B
- * - Tim Fish
- * - Коренберг Марк (imac)
- * - Serhan Apaydın
- * - RomeroMsk
- * - vsn4ik
- * - JD Isaacks
- * - Bari Badamshin
- * - Jørn Ølmheim
- * - François B
- * - Коренберг Марк (imac)
- * - Serhan Apaydın
- * - RomeroMsk
- * - vsn4ik
- * - JD Isaacks
- * - Fellzo
- * - andrey-helldar
- * - Pavel Skripkin (psxx)
- * - AlexWalkerson
- * - Vladislav UnsealedOne
- */
-$transformDiff = function ($input) {
- return strtr($input, [
- 'неделя' => 'неделю',
- 'секунда' => 'секунду',
- 'минута' => 'минуту',
- ]);
-};
-
-return [
- 'year' => ':count год|:count года|:count лет',
- 'y' => ':count г.|:count г.|:count л.',
- 'a_year' => '{1}год|:count год|:count года|:count лет',
- 'month' => ':count месяц|:count месяца|:count месяцев',
- 'm' => ':count мес.',
- 'a_month' => '{1}месяц|:count месяц|:count месяца|:count месяцев',
- 'week' => ':count неделя|:count недели|:count недель',
- 'w' => ':count нед.',
- 'a_week' => '{1}неделя|:count неделю|:count недели|:count недель',
- 'day' => ':count день|:count дня|:count дней',
- 'd' => ':count д.',
- 'a_day' => '{1}день|:count день|:count дня|:count дней',
- 'hour' => ':count час|:count часа|:count часов',
- 'h' => ':count ч.',
- 'a_hour' => '{1}час|:count час|:count часа|:count часов',
- 'minute' => ':count минута|:count минуты|:count минут',
- 'min' => ':count мин.',
- 'a_minute' => '{1}минута|:count минута|:count минуты|:count минут',
- 'second' => ':count секунда|:count секунды|:count секунд',
- 's' => ':count сек.',
- 'a_second' => '{1}несколько секунд|:count секунду|:count секунды|:count секунд',
- 'ago' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' назад';
- },
- 'from_now' => function ($time) use ($transformDiff) {
- return 'через '.$transformDiff($time);
- },
- 'after' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' после';
- },
- 'before' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' до';
- },
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY г.',
- 'LLL' => 'D MMMM YYYY г., H:mm',
- 'LLLL' => 'dddd, D MMMM YYYY г., H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Сегодня, в] LT',
- 'nextDay' => '[Завтра, в] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
- if ($current->week !== $other->week) {
- switch ($current->dayOfWeek) {
- case 0:
- return '[В следующее] dddd, [в] LT';
- case 1:
- case 2:
- case 4:
- return '[В следующий] dddd, [в] LT';
- case 3:
- case 5:
- case 6:
- return '[В следующую] dddd, [в] LT';
- }
- }
-
- if ($current->dayOfWeek === 2) {
- return '[Во] dddd, [в] LT';
- }
-
- return '[В] dddd, [в] LT';
- },
- 'lastDay' => '[Вчера, в] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
- if ($current->week !== $other->week) {
- switch ($current->dayOfWeek) {
- case 0:
- return '[В прошлое] dddd, [в] LT';
- case 1:
- case 2:
- case 4:
- return '[В прошлый] dddd, [в] LT';
- case 3:
- case 5:
- case 6:
- return '[В прошлую] dddd, [в] LT';
- }
- }
-
- if ($current->dayOfWeek === 2) {
- return '[Во] dddd, [в] LT';
- }
-
- return '[В] dddd, [в] LT';
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'M':
- case 'd':
- case 'DDD':
- return $number.'-й';
- case 'D':
- return $number.'-го';
- case 'w':
- case 'W':
- return $number.'-я';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'ночи';
- }
- if ($hour < 12) {
- return 'утра';
- }
- if ($hour < 17) {
- return 'дня';
- }
-
- return 'вечера';
- },
- 'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
- 'months_standalone' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
- 'months_short' => ['янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'months_short_standalone' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'months_regexp' => '/DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу'],
- 'weekdays_standalone' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
- 'weekdays_short' => ['вск', 'пнд', 'втр', 'срд', 'чтв', 'птн', 'сбт'],
- 'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
- 'weekdays_regexp' => '/\[\s*(В|в)\s*((?:прошлую|следующую|эту)\s*)?\]\s*dddd/',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' и '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ru.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ru.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ru.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ru.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ru.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - RFC 2319 bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ru.php', [
- 'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
- 'weekdays_short' => ['вск', 'пнд', 'вто', 'срд', 'чтв', 'птн', 'суб'],
- 'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'су'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/rw_RW.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Rwanda Steve Murphy murf@e-tools.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Mutarama', 'Gashyantare', 'Werurwe', 'Mata', 'Gicuransi', 'Kamena', 'Nyakanga', 'Kanama', 'Nzeli', 'Ukwakira', 'Ugushyingo', 'Ukuboza'],
- 'months_short' => ['Mut', 'Gas', 'Wer', 'Mat', 'Gic', 'Kam', 'Nya', 'Kan', 'Nze', 'Ukw', 'Ugu', 'Uku'],
- 'weekdays' => ['Ku cyumweru', 'Kuwa mbere', 'Kuwa kabiri', 'Kuwa gatatu', 'Kuwa kane', 'Kuwa gatanu', 'Kuwa gatandatu'],
- 'weekdays_short' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'],
- 'weekdays_min' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'second' => ':count vuna', // less reliable
- 's' => ':count vuna', // less reliable
- 'a_second' => ':count vuna', // less reliable
-
- 'year' => 'aka :count',
- 'y' => 'aka :count',
- 'a_year' => 'aka :count',
-
- 'month' => 'ezi :count',
- 'm' => 'ezi :count',
- 'a_month' => 'ezi :count',
-
- 'week' => ':count icyumweru',
- 'w' => ':count icyumweru',
- 'a_week' => ':count icyumweru',
-
- 'day' => ':count nsi',
- 'd' => ':count nsi',
- 'a_day' => ':count nsi',
-
- 'hour' => 'saha :count',
- 'h' => 'saha :count',
- 'a_hour' => 'saha :count',
-
- 'minute' => ':count -nzinya',
- 'min' => ':count -nzinya',
- 'a_minute' => ':count -nzinya',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['utuko', 'kyiukonyi'],
- 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sa_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - The Debian project Christian Perrier bubulle@debian.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D-MM-YY',
- ],
- 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'weekdays' => ['रविवासर:', 'सोमवासर:', 'मंगलवासर:', 'बुधवासर:', 'बृहस्पतिवासरः', 'शुक्रवासर', 'शनिवासर:'],
- 'weekdays_short' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'],
- 'weekdays_min' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-
- 'minute' => ':count होरा', // less reliable
- 'min' => ':count होरा', // less reliable
- 'a_minute' => ':count होरा', // less reliable
-
- 'year' => ':count वर्ष',
- 'y' => ':count वर्ष',
- 'a_year' => ':count वर्ष',
-
- 'month' => ':count मास',
- 'm' => ':count मास',
- 'a_month' => ':count मास',
-
- 'week' => ':count सप्ताहः saptahaĥ',
- 'w' => ':count सप्ताहः saptahaĥ',
- 'a_week' => ':count सप्ताहः saptahaĥ',
-
- 'day' => ':count दिन',
- 'd' => ':count दिन',
- 'a_day' => ':count दिन',
-
- 'hour' => ':count घण्टा',
- 'h' => ':count घण्टा',
- 'a_hour' => ':count घण्टा',
-
- 'second' => ':count द्वितीयः',
- 's' => ':count द्वितीयः',
- 'a_second' => ':count द्वितीयः',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sah_RU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Valery Timiriliyev Valery Timiriliyev timiriliyev@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/ru.php', [
- 'formats' => [
- 'L' => 'YYYY.MM.DD',
- ],
- 'months' => ['тохсунньу', 'олунньу', 'кулун тутар', 'муус устар', 'ыам ыйын', 'бэс ыйын', 'от ыйын', 'атырдьах ыйын', 'балаҕан ыйын', 'алтынньы', 'сэтинньи', 'ахсынньы'],
- 'months_short' => ['тохс', 'олун', 'кул', 'муус', 'ыам', 'бэс', 'от', 'атыр', 'бал', 'алт', 'сэт', 'ахс'],
- 'weekdays' => ['баскыһыанньа', 'бэнидиэнньик', 'оптуорунньук', 'сэрэдэ', 'чэппиэр', 'бээтинсэ', 'субуота'],
- 'weekdays_short' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'],
- 'weekdays_min' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Tesiran', 'Teipa'],
- 'weekdays' => ['Mderot ee are', 'Mderot ee kuni', 'Mderot ee ong’wan', 'Mderot ee inet', 'Mderot ee ile', 'Mderot ee sapa', 'Mderot ee kwe'],
- 'weekdays_short' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
- 'weekdays_min' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
- 'months' => ['Lapa le obo', 'Lapa le waare', 'Lapa le okuni', 'Lapa le ong’wan', 'Lapa le imet', 'Lapa le ile', 'Lapa le sapa', 'Lapa le isiet', 'Lapa le saal', 'Lapa le tomon', 'Lapa le tomon obo', 'Lapa le tomon waare'],
- 'months_short' => ['Obo', 'Waa', 'Oku', 'Ong', 'Ime', 'Ile', 'Sap', 'Isi', 'Saa', 'Tom', 'Tob', 'Tow'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sat_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat Pune libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'],
- 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'],
- 'weekdays' => ['सिंगेमाँहाँ', 'ओतेमाँहाँ', 'बालेमाँहाँ', 'सागुनमाँहाँ', 'सारदीमाँहाँ', 'जारुममाँहाँ', 'ञुहुममाँहाँ'],
- 'weekdays_short' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'],
- 'weekdays_min' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'],
- 'day_of_first_week_of_year' => 1,
-
- 'month' => ':count ńindạ cando', // less reliable
- 'm' => ':count ńindạ cando', // less reliable
- 'a_month' => ':count ńindạ cando', // less reliable
-
- 'week' => ':count mãhã', // less reliable
- 'w' => ':count mãhã', // less reliable
- 'a_week' => ':count mãhã', // less reliable
-
- 'hour' => ':count ᱥᱳᱱᱚ', // less reliable
- 'h' => ':count ᱥᱳᱱᱚ', // less reliable
- 'a_hour' => ':count ᱥᱳᱱᱚ', // less reliable
-
- 'minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable
- 'min' => ':count ᱯᱤᱞᱪᱩ', // less reliable
- 'a_minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable
-
- 'second' => ':count ar', // less reliable
- 's' => ':count ar', // less reliable
- 'a_second' => ':count ar', // less reliable
-
- 'year' => ':count ne̲s',
- 'y' => ':count ne̲s',
- 'a_year' => ':count ne̲s',
-
- 'day' => ':count ᱫᱤᱱ',
- 'd' => ':count ᱫᱤᱱ',
- 'a_day' => ':count ᱫᱤᱱ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Lwamilawu', 'Pashamihe'],
- 'weekdays' => ['Mulungu', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alahamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'months' => ['Mupalangulwa', 'Mwitope', 'Mushende', 'Munyi', 'Mushende Magali', 'Mujimbi', 'Mushipepo', 'Mupuguto', 'Munyense', 'Mokhu', 'Musongandembwe', 'Muhaano'],
- 'months_short' => ['Mup', 'Mwi', 'Msh', 'Mun', 'Mag', 'Muj', 'Msp', 'Mpg', 'Mye', 'Mok', 'Mus', 'Muh'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sc_IT.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Sardinian Translators Team Massimeddu Cireddu massimeddu@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD. MM. YY',
- ],
- 'months' => ['Ghennàrgiu', 'Freàrgiu', 'Martzu', 'Abrile', 'Maju', 'Làmpadas', 'Argiolas//Trìulas', 'Austu', 'Cabudanni', 'Santugaine//Ladàmine', 'Onniasantu//Santandria', 'Nadale//Idas'],
- 'months_short' => ['Ghe', 'Fre', 'Mar', 'Abr', 'Maj', 'Làm', 'Arg', 'Aus', 'Cab', 'Lad', 'Onn', 'Nad'],
- 'weekdays' => ['Domìnigu', 'Lunis', 'Martis', 'Mèrcuris', 'Giòbia', 'Chenàbura', 'Sàbadu'],
- 'weekdays_short' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'],
- 'weekdays_min' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'minute' => ':count mementu', // less reliable
- 'min' => ':count mementu', // less reliable
- 'a_minute' => ':count mementu', // less reliable
-
- 'year' => ':count annu',
- 'y' => ':count annu',
- 'a_year' => ':count annu',
-
- 'month' => ':count mese',
- 'm' => ':count mese',
- 'a_month' => ':count mese',
-
- 'week' => ':count chida',
- 'w' => ':count chida',
- 'a_week' => ':count chida',
-
- 'day' => ':count dí',
- 'd' => ':count dí',
- 'a_day' => ':count dí',
-
- 'hour' => ':count ora',
- 'h' => ':count ora',
- 'a_hour' => ':count ora',
-
- 'second' => ':count secundu',
- 's' => ':count secundu',
- 'a_second' => ':count secundu',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
-}, 'scr');
-
-return require __DIR__.'/sh.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-$months = [
- 'جنوري',
- 'فيبروري',
- 'مارچ',
- 'اپريل',
- 'مئي',
- 'جون',
- 'جولاءِ',
- 'آگسٽ',
- 'سيپٽمبر',
- 'آڪٽوبر',
- 'نومبر',
- 'ڊسمبر',
-];
-
-$weekdays = [
- 'آچر',
- 'سومر',
- 'اڱارو',
- 'اربع',
- 'خميس',
- 'جمع',
- 'ڇنڇر',
-];
-
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'sd');
-
-/*
- * Authors:
- * - Narain Sagar
- * - Sawood Alam
- * - Narain Sagar
- */
-return [
- 'year' => 'هڪ سال|:count سال',
- 'month' => 'هڪ مهينو|:count مهينا',
- 'week' => 'ھڪ ھفتو|:count هفتا',
- 'day' => 'هڪ ڏينهن|:count ڏينهن',
- 'hour' => 'هڪ ڪلاڪ|:count ڪلاڪ',
- 'minute' => 'هڪ منٽ|:count منٽ',
- 'second' => 'چند سيڪنڊ|:count سيڪنڊ',
- 'ago' => ':time اڳ',
- 'from_now' => ':time پوء',
- 'diff_yesterday' => 'ڪالهه',
- 'diff_tomorrow' => 'سڀاڻي',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd، D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[اڄ] LT',
- 'nextDay' => '[سڀاڻي] LT',
- 'nextWeek' => 'dddd [اڳين هفتي تي] LT',
- 'lastDay' => '[ڪالهه] LT',
- 'lastWeek' => '[گزريل هفتي] dddd [تي] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['صبح', 'شام'],
- 'months' => $months,
- 'months_short' => $months,
- 'weekdays' => $weekdays,
- 'weekdays_short' => $weekdays,
- 'weekdays_min' => $weekdays,
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => ['، ', ' ۽ '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat, Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/sd.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'],
- 'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'],
- 'weekdays' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
- 'weekdays_short' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
- 'weekdays_min' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat, Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/sd.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'],
- 'months_short' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'],
- 'weekdays' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
- 'weekdays_short' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
- 'weekdays_min' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['म.पू.', 'म.नं.'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'se');
-
-/*
- * Authors:
- * - François B
- * - Karamell
- */
-return [
- 'year' => ':count jahki|:count jagit',
- 'a_year' => 'okta jahki|:count jagit',
- 'y' => ':count j.',
- 'month' => ':count mánnu|:count mánut',
- 'a_month' => 'okta mánnu|:count mánut',
- 'm' => ':count mán.',
- 'week' => ':count vahkku|:count vahkku',
- 'a_week' => 'okta vahkku|:count vahkku',
- 'w' => ':count v.',
- 'day' => ':count beaivi|:count beaivvit',
- 'a_day' => 'okta beaivi|:count beaivvit',
- 'd' => ':count b.',
- 'hour' => ':count diimmu|:count diimmut',
- 'a_hour' => 'okta diimmu|:count diimmut',
- 'h' => ':count d.',
- 'minute' => ':count minuhta|:count minuhtat',
- 'a_minute' => 'okta minuhta|:count minuhtat',
- 'min' => ':count min.',
- 'second' => ':count sekunddat|:count sekunddat',
- 'a_second' => 'moadde sekunddat|:count sekunddat',
- 's' => ':count s.',
- 'ago' => 'maŋit :time',
- 'from_now' => ':time geažes',
- 'diff_yesterday' => 'ikte',
- 'diff_tomorrow' => 'ihttin',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'MMMM D. [b.] YYYY',
- 'LLL' => 'MMMM D. [b.] YYYY [ti.] HH:mm',
- 'LLLL' => 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[otne ti] LT',
- 'nextDay' => '[ihttin ti] LT',
- 'nextWeek' => 'dddd [ti] LT',
- 'lastDay' => '[ikte ti] LT',
- 'lastWeek' => '[ovddit] dddd [ti] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
- 'months_short' => ['ođđj', 'guov', 'njuk', 'cuo', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
- 'weekdays' => ['sotnabeaivi', 'vuossárga', 'maŋŋebárga', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvardat'],
- 'weekdays_short' => ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear', 'láv'],
- 'weekdays_min' => ['s', 'v', 'm', 'g', 'd', 'b', 'L'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' ja '],
- 'meridiem' => ['i.b.', 'e.b.'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/se.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
- 'months_short' => ['ođđj', 'guov', 'njuk', 'cuoŋ', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
- 'weekdays' => ['sotnabeaivi', 'mánnodat', 'disdat', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvordat'],
- 'weekdays_short' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'],
- 'weekdays_min' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'],
- 'meridiem' => ['i', 'e'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/se.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/se.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['Dimingu', 'Chiposi', 'Chipiri', 'Chitatu', 'Chinai', 'Chishanu', 'Sabudu'],
- 'weekdays_short' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
- 'weekdays_min' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
- 'months' => ['Janeiro', 'Fevreiro', 'Marco', 'Abril', 'Maio', 'Junho', 'Julho', 'Augusto', 'Setembro', 'Otubro', 'Novembro', 'Decembro'],
- 'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Aug', 'Set', 'Otu', 'Nov', 'Dec'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'd [de] MMM [de] YYYY',
- 'LLL' => 'd [de] MMMM [de] YYYY HH:mm',
- 'LLLL' => 'dddd, d [de] MMMM [de] YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Adduha', 'Aluula'],
- 'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa', 'Alzuma', 'Asibti'],
- 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
- 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
- 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
- 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'month' => ':count alaada', // less reliable
- 'm' => ':count alaada', // less reliable
- 'a_month' => ':count alaada', // less reliable
-
- 'hour' => ':count ɲaajin', // less reliable
- 'h' => ':count ɲaajin', // less reliable
- 'a_hour' => ':count ɲaajin', // less reliable
-
- 'minute' => ':count zarbu', // less reliable
- 'min' => ':count zarbu', // less reliable
- 'a_minute' => ':count zarbu', // less reliable
-
- 'year' => ':count jiiri',
- 'y' => ':count jiiri',
- 'a_year' => ':count jiiri',
-
- 'week' => ':count jirbiiyye',
- 'w' => ':count jirbiiyye',
- 'a_week' => ':count jirbiiyye',
-
- 'day' => ':count zaari',
- 'd' => ':count zaari',
- 'a_day' => ':count zaari',
-
- 'second' => ':count ihinkante',
- 's' => ':count ihinkante',
- 'a_second' => ':count ihinkante',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['ND', 'LK'],
- 'weekdays' => ['Bikua-ôko', 'Bïkua-ûse', 'Bïkua-ptâ', 'Bïkua-usïö', 'Bïkua-okü', 'Lâpôsö', 'Lâyenga'],
- 'weekdays_short' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
- 'weekdays_min' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
- 'months' => ['Nyenye', 'Fulundïgi', 'Mbängü', 'Ngubùe', 'Bêläwü', 'Föndo', 'Lengua', 'Kükürü', 'Mvuka', 'Ngberere', 'Nabändüru', 'Kakauka'],
- 'months_short' => ['Nye', 'Ful', 'Mbä', 'Ngu', 'Bêl', 'Fön', 'Len', 'Kük', 'Mvu', 'Ngb', 'Nab', 'Kak'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count dā', // less reliable
- 'y' => ':count dā', // less reliable
- 'a_year' => ':count dā', // less reliable
-
- 'week' => ':count bïkua-okü', // less reliable
- 'w' => ':count bïkua-okü', // less reliable
- 'a_week' => ':count bïkua-okü', // less reliable
-
- 'day' => ':count ziggawâ', // less reliable
- 'd' => ':count ziggawâ', // less reliable
- 'a_day' => ':count ziggawâ', // less reliable
-
- 'hour' => ':count yângâködörö', // less reliable
- 'h' => ':count yângâködörö', // less reliable
- 'a_hour' => ':count yângâködörö', // less reliable
-
- 'second' => ':count bïkua-ôko', // less reliable
- 's' => ':count bïkua-ôko', // less reliable
- 'a_second' => ':count bïkua-ôko', // less reliable
-
- 'month' => ':count Nze tî ngu',
- 'm' => ':count Nze tî ngu',
- 'a_month' => ':count Nze tî ngu',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sgs_LT.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Arnas Udovičius bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY.MM.DD',
- ],
- 'months' => ['sausė', 'vasarė', 'kuova', 'balondė', 'gegožės', 'bėrželė', 'lëpas', 'rogpjūtė', 'siejės', 'spalė', 'lapkrėstė', 'grůdė'],
- 'months_short' => ['Sau', 'Vas', 'Kuo', 'Bal', 'Geg', 'Bėr', 'Lëp', 'Rgp', 'Sie', 'Spa', 'Lap', 'Grd'],
- 'weekdays' => ['nedielės dëna', 'panedielis', 'oterninks', 'sereda', 'četvergs', 'petnīčė', 'sobata'],
- 'weekdays_short' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'],
- 'weekdays_min' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'minute' => ':count mažos', // less reliable
- 'min' => ':count mažos', // less reliable
- 'a_minute' => ':count mažos', // less reliable
-
- 'year' => ':count metā',
- 'y' => ':count metā',
- 'a_year' => ':count metā',
-
- 'month' => ':count mienou',
- 'm' => ':count mienou',
- 'a_month' => ':count mienou',
-
- 'week' => ':count nedielė',
- 'w' => ':count nedielė',
- 'a_week' => ':count nedielė',
-
- 'day' => ':count dīna',
- 'd' => ':count dīna',
- 'a_day' => ':count dīna',
-
- 'hour' => ':count adīna',
- 'h' => ':count adīna',
- 'a_hour' => ':count adīna',
-
- 'second' => ':count Sekondė',
- 's' => ':count Sekondė',
- 'a_second' => ':count Sekondė',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
-}, 'sh');
-
-/*
- * Authors:
- * - Томица Кораћ
- * - Enrique Vidal
- * - Christopher Dell
- * - dmilisic
- * - danijel
- */
-return [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'MMMM D, YYYY',
- 'LLL' => 'DD MMM HH:mm',
- 'LLLL' => 'MMMM DD, YYYY HH:mm',
- ],
- 'year' => ':count godina|:count godine|:count godina',
- 'y' => ':count godina|:count godine|:count godina',
- 'month' => ':count mesec|:count meseca|:count meseci',
- 'm' => ':count mesec|:count meseca|:count meseci',
- 'week' => ':count nedelja|:count nedelje|:count nedelja',
- 'w' => ':count nedelja|:count nedelje|:count nedelja',
- 'day' => ':count dan|:count dana|:count dana',
- 'd' => ':count dan|:count dana|:count dana',
- 'hour' => ':count čas|:count časa|:count časova',
- 'h' => ':count čas|:count časa|:count časova',
- 'minute' => ':count minut|:count minuta|:count minuta',
- 'min' => ':count minut|:count minuta|:count minuta',
- 'second' => ':count sekund|:count sekunda|:count sekundi',
- 's' => ':count sekund|:count sekunda|:count sekundi',
- 'ago' => 'pre :time',
- 'from_now' => 'za :time',
- 'after' => 'nakon :time',
- 'before' => ':time raniјe',
- 'weekdays' => ['Nedelja', 'Ponedeljak', 'Utorak', 'Sreda', 'Četvrtak', 'Petak', 'Subota'],
- 'weekdays_short' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'],
- 'weekdays_min' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'],
- 'months' => ['Januar', 'Februar', 'Mart', 'April', 'Maj', 'Jun', 'Jul', 'Avgust', 'Septembar', 'Oktobar', 'Novembar', 'Decembar'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'],
- 'list' => [', ', ' i '],
- 'meridiem' => ['pre podne', 'po podne'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
- 'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
- 'weekdays_short' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
- 'weekdays_min' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
- 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
- 'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵜⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'year' => ':count aseggwas',
- 'y' => ':count aseggwas',
- 'a_year' => ':count aseggwas',
-
- 'month' => ':count ayyur',
- 'm' => ':count ayyur',
- 'a_month' => ':count ayyur',
-
- 'week' => ':count imalass',
- 'w' => ':count imalass',
- 'a_week' => ':count imalass',
-
- 'day' => ':count ass',
- 'd' => ':count ass',
- 'a_day' => ':count ass',
-
- 'hour' => ':count urɣ', // less reliable
- 'h' => ':count urɣ', // less reliable
- 'a_hour' => ':count urɣ', // less reliable
-
- 'minute' => ':count ⴰⵎⵥⵉ', // less reliable
- 'min' => ':count ⴰⵎⵥⵉ', // less reliable
- 'a_minute' => ':count ⴰⵎⵥⵉ', // less reliable
-
- 'second' => ':count sin', // less reliable
- 's' => ':count sin', // less reliable
- 'a_second' => ':count sin', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/shi.php', [
- 'meridiem' => ['tifawt', 'tadggʷat'],
- 'weekdays' => ['asamas', 'aynas', 'asinas', 'akṛas', 'akwas', 'asimwas', 'asiḍyas'],
- 'weekdays_short' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
- 'weekdays_min' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
- 'months' => ['innayr', 'bṛayṛ', 'maṛṣ', 'ibrir', 'mayyu', 'yunyu', 'yulyuz', 'ɣuct', 'cutanbir', 'ktubr', 'nuwanbir', 'dujanbir'],
- 'months_short' => ['inn', 'bṛa', 'maṛ', 'ibr', 'may', 'yun', 'yul', 'ɣuc', 'cut', 'ktu', 'nuw', 'duj'],
- 'first_day_of_week' => 6,
- 'weekend' => [5, 6],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-
- 'minute' => ':count agur', // less reliable
- 'min' => ':count agur', // less reliable
- 'a_minute' => ':count agur', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/shi.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/shn_MM.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - ubuntu Myanmar LoCo Team http://www.ubuntu-mm.net Bone Pyae Sone bone.burma@mail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'OY MMM OD dddd',
- ],
- 'months' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'],
- 'months_short' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'],
- 'weekdays' => ['ဝၼ်းဢႃးတိတ်ႉ', 'ဝၼ်းၸၼ်', 'ဝၼ်းဢၢင်းၵၢၼ်း', 'ဝၼ်းပူတ်ႉ', 'ဝၼ်းၽတ်း', 'ဝၼ်းသုၵ်း', 'ဝၼ်းသဝ်'],
- 'weekdays_short' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'],
- 'weekdays_min' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'],
- 'alt_numbers' => ['႐႐', '႐႑', '႐႒', '႐႓', '႐႔', '႐႕', '႐႖', '႐႗', '႐႘', '႐႙', '႑႐', '႑႑', '႑႒', '႑႓', '႑႔', '႑႕', '႑႖', '႑႗', '႑႘', '႑႙', '႒႐', '႒႑', '႒႒', '႒႓', '႒႔', '႒႕', '႒႖', '႒႗', '႒႘', '႒႙', '႓႐', '႓႑', '႓႒', '႓႓', '႓႔', '႓႕', '႓႖', '႓႗', '႓႘', '႓႙', '႔႐', '႔႑', '႔႒', '႔႓', '႔႔', '႔႕', '႔႖', '႔႗', '႔႘', '႔႙', '႕႐', '႕႑', '႕႒', '႕႓', '႕႔', '႕႕', '႕႖', '႕႗', '႕႘', '႕႙', '႖႐', '႖႑', '႖႒', '႖႓', '႖႔', '႖႕', '႖႖', '႖႗', '႖႘', '႖႙', '႗႐', '႗႑', '႗႒', '႗႓', '႗႔', '႗႕', '႗႖', '႗႗', '႗႘', '႗႙', '႘႐', '႘႑', '႘႒', '႘႓', '႘႔', '႘႕', '႘႖', '႘႗', '႘႘', '႘႙', '႙႐', '႙႑', '႙႒', '႙႓', '႙႔', '႙႕', '႙႖', '႙႗', '႙႘', '႙႙'],
- 'meridiem' => ['ၵၢင်ၼႂ်', 'တၢမ်းၶမ်ႈ'],
-
- 'month' => ':count လိူၼ်', // less reliable
- 'm' => ':count လိူၼ်', // less reliable
- 'a_month' => ':count လိူၼ်', // less reliable
-
- 'week' => ':count ဝၼ်း', // less reliable
- 'w' => ':count ဝၼ်း', // less reliable
- 'a_week' => ':count ဝၼ်း', // less reliable
-
- 'hour' => ':count ຕີ', // less reliable
- 'h' => ':count ຕີ', // less reliable
- 'a_hour' => ':count ຕີ', // less reliable
-
- 'minute' => ':count ເດັກ', // less reliable
- 'min' => ':count ເດັກ', // less reliable
- 'a_minute' => ':count ເດັກ', // less reliable
-
- 'second' => ':count ဢိုၼ်ႇ', // less reliable
- 's' => ':count ဢိုၼ်ႇ', // less reliable
- 'a_second' => ':count ဢိုၼ်ႇ', // less reliable
-
- 'year' => ':count ပီ',
- 'y' => ':count ပီ',
- 'a_year' => ':count ပီ',
-
- 'day' => ':count ກາງວັນ',
- 'd' => ':count ກາງວັນ',
- 'a_day' => ':count ກາງວັນ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/shs_CA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Neskie Manuel bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Pellkwet̓min', 'Pelctsipwen̓ten', 'Pellsqépts', 'Peslléwten', 'Pell7ell7é7llqten', 'Pelltspéntsk', 'Pelltqwelq̓wél̓t', 'Pellct̓éxel̓cten', 'Pesqelqlélten', 'Pesllwélsten', 'Pellc7ell7é7llcwten̓', 'Pelltetétq̓em'],
- 'months_short' => ['Kwe', 'Tsi', 'Sqe', 'Éwt', 'Ell', 'Tsp', 'Tqw', 'Ct̓é', 'Qel', 'Wél', 'U7l', 'Tet'],
- 'weekdays' => ['Sxetspesq̓t', 'Spetkesq̓t', 'Selesq̓t', 'Skellesq̓t', 'Smesesq̓t', 'Stselkstesq̓t', 'Stqmekstesq̓t'],
- 'weekdays_short' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'],
- 'weekdays_min' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count sqlélten', // less reliable
- 'y' => ':count sqlélten', // less reliable
- 'a_year' => ':count sqlélten', // less reliable
-
- 'month' => ':count swewll', // less reliable
- 'm' => ':count swewll', // less reliable
- 'a_month' => ':count swewll', // less reliable
-
- 'hour' => ':count seqwlút', // less reliable
- 'h' => ':count seqwlút', // less reliable
- 'a_hour' => ':count seqwlút', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'si');
-
-/*
- * Authors:
- * - François B
- * - Serhan Apaydın
- * - JD Isaacks
- */
-return [
- 'year' => 'වසර|වසර :count',
- 'month' => 'මාසය|මාස :count',
- 'week' => 'සතියක්|සති :count යි',
- 'day' => 'දිනය|දින :count',
- 'hour' => 'පැය|පැය :count',
- 'minute' => 'මිනිත්තුව|මිනිත්තු :count',
- 'second' => 'තත්පර කිහිපය|තත්පර :count',
- 'ago' => ':timeකට පෙර',
- 'from_now' => ':timeකින්',
- 'diff_yesterday' => 'ඊයේ',
- 'diff_tomorrow' => 'හෙට',
- 'formats' => [
- 'LT' => 'a h:mm',
- 'LTS' => 'a h:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY MMMM D',
- 'LLL' => 'YYYY MMMM D, a h:mm',
- 'LLLL' => 'YYYY MMMM D [වැනි] dddd, a h:mm:ss',
- ],
- 'calendar' => [
- 'sameDay' => '[අද] LT[ට]',
- 'nextDay' => '[හෙට] LT[ට]',
- 'nextWeek' => 'dddd LT[ට]',
- 'lastDay' => '[ඊයේ] LT[ට]',
- 'lastWeek' => '[පසුගිය] dddd LT[ට]',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number වැනි',
- 'meridiem' => ['පෙර වරු', 'පස් වරු', 'පෙ.ව.', 'ප.ව.'],
- 'months' => ['ජනවාරි', 'පෙබරවාරි', 'මාර්තු', 'අප්රේල්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝස්තු', 'සැප්තැම්බර්', 'ඔක්තෝබර්', 'නොවැම්බර්', 'දෙසැම්බර්'],
- 'months_short' => ['ජන', 'පෙබ', 'මාර්', 'අප්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
- 'weekdays' => ['ඉරිදා', 'සඳුදා', 'අඟහරුවාදා', 'බදාදා', 'බ්රහස්පතින්දා', 'සිකුරාදා', 'සෙනසුරාදා'],
- 'weekdays_short' => ['ඉරි', 'සඳු', 'අඟ', 'බදා', 'බ්රහ', 'සිකු', 'සෙන'],
- 'weekdays_min' => ['ඉ', 'ස', 'අ', 'බ', 'බ්ර', 'සි', 'සෙ'],
- 'first_day_of_week' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/si.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sid_ET.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- 'weekdays' => ['Sambata', 'Sanyo', 'Maakisanyo', 'Roowe', 'Hamuse', 'Arbe', 'Qidaame'],
- 'weekdays_short' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'],
- 'weekdays_min' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['soodo', 'hawwaro'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Martin Suja
- * - Tsutomu Kuroda
- * - tjku
- * - Max Melentiev
- * - Juanito Fatas
- * - Ivan Stana
- * - Akira Matsuda
- * - Christopher Dell
- * - James McKinney
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Jozef Fulop
- * - Nicolás Hock Isaza
- * - Tom Hughes
- * - Simon Hürlimann (CyT)
- * - jofi
- * - Jakub ADAMEC
- * - Marek Adamický
- */
-return [
- 'year' => 'rok|:count roky|:count rokov',
- 'y' => ':count r',
- 'month' => 'mesiac|:count mesiace|:count mesiacov',
- 'm' => ':count m',
- 'week' => 'týždeň|:count týždne|:count týždňov',
- 'w' => ':count t',
- 'day' => 'deň|:count dni|:count dní',
- 'd' => ':count d',
- 'hour' => 'hodinu|:count hodiny|:count hodín',
- 'h' => ':count h',
- 'minute' => 'minútu|:count minúty|:count minút',
- 'min' => ':count min',
- 'second' => 'sekundu|:count sekundy|:count sekúnd',
- 's' => ':count s',
- 'ago' => 'pred :time',
- 'from_now' => 'za :time',
- 'after' => 'o :time neskôr',
- 'before' => ':time predtým',
- 'year_ago' => 'rokom|:count rokmi|:count rokmi',
- 'month_ago' => 'mesiacom|:count mesiacmi|:count mesiacmi',
- 'week_ago' => 'týždňom|:count týždňami|:count týždňami',
- 'day_ago' => 'dňom|:count dňami|:count dňami',
- 'hour_ago' => 'hodinou|:count hodinami|:count hodinami',
- 'minute_ago' => 'minútou|:count minútami|:count minútami',
- 'second_ago' => 'sekundou|:count sekundami|:count sekundami',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' a '],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'DD. MMMM YYYY',
- 'LLL' => 'D. M. HH:mm',
- 'LLLL' => 'dddd D. MMMM YYYY HH:mm',
- ],
- 'weekdays' => ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok', 'sobota'],
- 'weekdays_short' => ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
- 'weekdays_min' => ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
- 'months' => ['január', 'február', 'marec', 'apríl', 'máj', 'jún', 'júl', 'august', 'september', 'október', 'november', 'december'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'meridiem' => ['dopoludnia', 'popoludní'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sk.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - tjku
- * - Max Melentiev
- * - Juanito Fatas
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Nicolás Hock Isaza
- * - Miha Rebernik
- * - Gal Jakič
- * - Glavić
- * - Anže Časar
- */
-return [
- 'year' => ':count leto|:count leti|:count leta|:count let',
- 'y' => ':count leto|:count leti|:count leta|:count let',
- 'month' => ':count mesec|:count meseca|:count mesece|:count mesecev',
- 'm' => ':count mesec|:count meseca|:count mesece|:count mesecev',
- 'week' => ':count teden|:count tedna|:count tedne|:count tednov',
- 'w' => ':count teden|:count tedna|:count tedne|:count tednov',
- 'day' => ':count dan|:count dni|:count dni|:count dni',
- 'd' => ':count dan|:count dni|:count dni|:count dni',
- 'hour' => ':count uro|:count uri|:count ure|:count ur',
- 'h' => ':count uro|:count uri|:count ure|:count ur',
- 'minute' => ':count minuto|:count minuti|:count minute|:count minut',
- 'min' => ':count minuto|:count minuti|:count minute|:count minut',
- 'second' => ':count sekundo|:count sekundi|:count sekunde|:count sekund',
- 's' => ':count sekundo|:count sekundi|:count sekunde|:count sekund',
- 'year_ago' => ':count letom|:count leti|:count leti|:count leti',
- 'month_ago' => ':count mesecem|:count meseci|:count meseci|:count meseci',
- 'week_ago' => ':count tednom|:count tednoma|:count tedni|:count tedni',
- 'day_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi',
- 'hour_ago' => ':count uro|:count urama|:count urami|:count urami',
- 'minute_ago' => ':count minuto|:count minutama|:count minutami|:count minutami',
- 'second_ago' => ':count sekundo|:count sekundama|:count sekundami|:count sekundami',
- 'ago' => 'pred :time',
- 'from_now' => 'čez :time',
- 'after' => 'čez :time',
- 'before' => 'pred :time',
- 'diff_now' => 'ravnokar',
- 'diff_yesterday' => 'včeraj',
- 'diff_tomorrow' => 'jutri',
- 'diff_before_yesterday' => 'predvčerajšnjim',
- 'diff_after_tomorrow' => 'pojutrišnjem',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'period_start_date' => 'od :date',
- 'period_end_date' => 'do :date',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[danes ob] LT',
- 'nextDay' => '[jutri ob] LT',
- 'nextWeek' => 'dddd [ob] LT',
- 'lastDay' => '[včeraj ob] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[preteklo] [nedeljo] [ob] LT';
- case 1:
- return '[pretekli] [ponedeljek] [ob] LT';
- case 2:
- return '[pretekli] [torek] [ob] LT';
- case 3:
- return '[preteklo] [sredo] [ob] LT';
- case 4:
- return '[pretekli] [četrtek] [ob] LT';
- case 5:
- return '[pretekli] [petek] [ob] LT';
- case 6:
- return '[preteklo] [soboto] [ob] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'months' => ['Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij', 'Avgust', 'September', 'Oktober', 'November', 'December'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'],
- 'weekdays' => ['Nedelja', 'Ponedeljek', 'Torek', 'Sreda', 'Četrtek', 'Petek', 'Sobota'],
- 'weekdays_short' => ['Ned', 'Pon', 'Tor', 'Sre', 'Čet', 'Pet', 'Sob'],
- 'weekdays_min' => ['Ne', 'Po', 'To', 'Sr', 'Če', 'Pe', 'So'],
- 'list' => [', ', ' in '],
- 'meridiem' => ['dopoldan', 'popoldan'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/sm_WS.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Ianuari', 'Fepuari', 'Mati', 'Aperila', 'Me', 'Iuni', 'Iulai', 'Auguso', 'Setema', 'Oketopa', 'Novema', 'Tesema'],
- 'months_short' => ['Ian', 'Fep', 'Mat', 'Ape', 'Me', 'Iun', 'Iul', 'Aug', 'Set', 'Oke', 'Nov', 'Tes'],
- 'weekdays' => ['Aso Sa', 'Aso Gafua', 'Aso Lua', 'Aso Lulu', 'Aso Tofi', 'Aso Farail', 'Aso To\'ana\'i'],
- 'weekdays_short' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''],
- 'weekdays_min' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''],
-
- 'hour' => ':count uati', // less reliable
- 'h' => ':count uati', // less reliable
- 'a_hour' => ':count uati', // less reliable
-
- 'minute' => ':count itiiti', // less reliable
- 'min' => ':count itiiti', // less reliable
- 'a_minute' => ':count itiiti', // less reliable
-
- 'second' => ':count lua', // less reliable
- 's' => ':count lua', // less reliable
- 'a_second' => ':count lua', // less reliable
-
- 'year' => ':count tausaga',
- 'y' => ':count tausaga',
- 'a_year' => ':count tausaga',
-
- 'month' => ':count māsina',
- 'm' => ':count māsina',
- 'a_month' => ':count māsina',
-
- 'week' => ':count vaiaso',
- 'w' => ':count vaiaso',
- 'a_week' => ':count vaiaso',
-
- 'day' => ':count aso',
- 'd' => ':count aso',
- 'a_day' => ':count aso',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['ip.', 'ep.'],
- 'weekdays' => ['pasepeeivi', 'vuossaargâ', 'majebaargâ', 'koskoho', 'tuorâstuv', 'vástuppeeivi', 'lávurduv'],
- 'weekdays_short' => ['pas', 'vuo', 'maj', 'kos', 'tuo', 'vás', 'láv'],
- 'weekdays_min' => ['pa', 'vu', 'ma', 'ko', 'tu', 'vá', 'lá'],
- 'weekdays_standalone' => ['pasepeivi', 'vuossargâ', 'majebargâ', 'koskokko', 'tuorâstâh', 'vástuppeivi', 'lávurdâh'],
- 'months' => ['uđđâivemáánu', 'kuovâmáánu', 'njuhčâmáánu', 'cuáŋuimáánu', 'vyesimáánu', 'kesimáánu', 'syeinimáánu', 'porgemáánu', 'čohčâmáánu', 'roovvâdmáánu', 'skammâmáánu', 'juovlâmáánu'],
- 'months_short' => ['uđiv', 'kuovâ', 'njuhčâ', 'cuáŋui', 'vyesi', 'kesi', 'syeini', 'porge', 'čohčâ', 'roovvâd', 'skammâ', 'juovlâ'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'H.mm',
- 'LTS' => 'H.mm.ss',
- 'L' => 'D.M.YYYY',
- 'LL' => 'MMM D. YYYY',
- 'LLL' => 'MMMM D. YYYY H.mm',
- 'LLLL' => 'dddd, MMMM D. YYYY H.mm',
- ],
-
- 'hour' => ':count äigi', // less reliable
- 'h' => ':count äigi', // less reliable
- 'a_hour' => ':count äigi', // less reliable
-
- 'year' => ':count ihe',
- 'y' => ':count ihe',
- 'a_year' => ':count ihe',
-
- 'month' => ':count mánuppaje',
- 'm' => ':count mánuppaje',
- 'a_month' => ':count mánuppaje',
-
- 'week' => ':count okko',
- 'w' => ':count okko',
- 'a_week' => ':count okko',
-
- 'day' => ':count peivi',
- 'd' => ':count peivi',
- 'a_day' => ':count peivi',
-
- 'minute' => ':count miinut',
- 'min' => ':count miinut',
- 'a_minute' => ':count miinut',
-
- 'second' => ':count nubbe',
- 's' => ':count nubbe',
- 'a_second' => ':count nubbe',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['a', 'p'],
- 'weekdays' => ['Svondo', 'Muvhuro', 'Chipiri', 'Chitatu', 'China', 'Chishanu', 'Mugovera'],
- 'weekdays_short' => ['Svo', 'Muv', 'Chp', 'Cht', 'Chn', 'Chs', 'Mug'],
- 'weekdays_min' => ['Sv', 'Mu', 'Cp', 'Ct', 'Cn', 'Cs', 'Mg'],
- 'months' => ['Ndira', 'Kukadzi', 'Kurume', 'Kubvumbi', 'Chivabvu', 'Chikumi', 'Chikunguru', 'Nyamavhuvhu', 'Gunyana', 'Gumiguru', 'Mbudzi', 'Zvita'],
- 'months_short' => ['Ndi', 'Kuk', 'Kur', 'Kub', 'Chv', 'Chk', 'Chg', 'Nya', 'Gun', 'Gum', 'Mbu', 'Zvi'],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
- ],
-
- 'year' => 'makore :count',
- 'y' => 'makore :count',
- 'a_year' => 'makore :count',
-
- 'month' => 'mwedzi :count',
- 'm' => 'mwedzi :count',
- 'a_month' => 'mwedzi :count',
-
- 'week' => 'vhiki :count',
- 'w' => 'vhiki :count',
- 'a_week' => 'vhiki :count',
-
- 'day' => 'mazuva :count',
- 'd' => 'mazuva :count',
- 'a_day' => 'mazuva :count',
-
- 'hour' => 'maawa :count',
- 'h' => 'maawa :count',
- 'a_hour' => 'maawa :count',
-
- 'minute' => 'minitsi :count',
- 'min' => 'minitsi :count',
- 'a_minute' => 'minitsi :count',
-
- 'second' => 'sekonzi :count',
- 's' => 'sekonzi :count',
- 'a_second' => 'sekonzi :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/so_DJ.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Bisha Koobaad', 'Bisha Labaad', 'Bisha Saddexaad', 'Bisha Afraad', 'Bisha Shanaad', 'Bisha Lixaad', 'Bisha Todobaad', 'Bisha Sideedaad', 'Bisha Sagaalaad', 'Bisha Tobnaad', 'Bisha Kow iyo Tobnaad', 'Bisha Laba iyo Tobnaad'],
- 'months_short' => ['Kob', 'Lab', 'Sad', 'Afr', 'Sha', 'Lix', 'Tod', 'Sid', 'Sag', 'Tob', 'KIT', 'LIT'],
- 'weekdays' => ['Axad', 'Isniin', 'Salaaso', 'Arbaco', 'Khamiis', 'Jimco', 'Sabti'],
- 'weekdays_short' => ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'weekdays_min' => ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['subaxnimo', 'galabnimo'],
-
- 'year' => ':count sanad',
- 'y' => ':count sanad',
- 'a_year' => ':count sanad',
-
- 'month' => ':count Bilaha',
- 'm' => ':count Bilaha',
- 'a_month' => ':count Bilaha',
-
- 'week' => ':count todobaad',
- 'w' => ':count todobaad',
- 'a_week' => ':count todobaad',
-
- 'day' => ':count maalin',
- 'd' => ':count maalin',
- 'a_day' => ':count maalin',
-
- 'hour' => ':count saacad',
- 'h' => ':count saacad',
- 'a_hour' => ':count saacad',
-
- 'minute' => ':count daqiiqad',
- 'min' => ':count daqiiqad',
- 'a_minute' => ':count daqiiqad',
-
- 'second' => ':count ilbiriqsi',
- 's' => ':count ilbiriqsi',
- 'a_second' => ':count ilbiriqsi',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Bisha Koobaad', 'Bisha Labaad', 'Bisha Saddexaad', 'Bisha Afraad', 'Bisha Shanaad', 'Bisha Lixaad', 'Bisha Todobaad', 'Bisha Sideedaad', 'Bisha Sagaalaad', 'Bisha Tobnaad', 'Bisha Kow iyo Tobnaad', 'Bisha Laba iyo Tobnaad'],
- 'months_short' => ['Kob', 'Lab', 'Sad', 'Afr', 'Sha', 'Lix', 'Tod', 'Sid', 'Sag', 'Tob', 'KIT', 'LIT'],
- 'weekdays' => ['Axad', 'Isniin', 'Salaaso', 'Arbaco', 'Khamiis', 'Jimco', 'Sabti'],
- 'weekdays_short' => ['Axd', 'Isn', 'Sal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'weekdays_min' => ['Axd', 'Isn', 'Sal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['subaxnimo', 'galabnimo'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Bisha Koobaad', 'Bisha Labaad', 'Bisha Saddexaad', 'Bisha Afraad', 'Bisha Shanaad', 'Bisha Lixaad', 'Bisha Todobaad', 'Bisha Sideedaad', 'Bisha Sagaalaad', 'Bisha Tobnaad', 'Bisha Kow iyo Tobnaad', 'Bisha Laba iyo Tobnaad'],
- 'months_short' => ['Kob', 'Lab', 'Sad', 'Afr', 'Sha', 'Lix', 'Tod', 'Sid', 'Sag', 'Tob', 'KIT', 'LIT'],
- 'weekdays' => ['Axad', 'Isniin', 'Salaaso', 'Arbaco', 'Khamiis', 'Jimco', 'Sabti'],
- 'weekdays_short' => ['Axd', 'Isn', 'Sal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'weekdays_min' => ['Axd', 'Isn', 'Sal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['subaxnimo', 'galabnimo'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Bisha Koobaad', 'Bisha Labaad', 'Bisha Saddexaad', 'Bisha Afraad', 'Bisha Shanaad', 'Bisha Lixaad', 'Bisha Todobaad', 'Bisha Sideedaad', 'Bisha Sagaalaad', 'Bisha Tobnaad', 'Bisha Kow iyo Tobnaad', 'Bisha Laba iyo Tobnaad'],
- 'months_short' => ['Kob', 'Lab', 'Sad', 'Afr', 'Sha', 'Lix', 'Tod', 'Sid', 'Sag', 'Tob', 'KIT', 'LIT'],
- 'weekdays' => ['Axad', 'Isniin', 'Salaaso', 'Arbaco', 'Khamiis', 'Jimco', 'Sabti'],
- 'weekdays_short' => ['Axd', 'Isn', 'Sal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'weekdays_min' => ['Axd', 'Isn', 'Sal', 'Arb', 'Kha', 'Jim', 'Sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['subaxnimo', 'galabnimo'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - JD Isaacks
- * - Fadion Dashi
- */
-return [
- 'year' => ':count vit|:count vjet',
- 'a_year' => 'një vit|:count vite',
- 'y' => ':count v.',
- 'month' => ':count muaj',
- 'a_month' => 'një muaj|:count muaj',
- 'm' => ':count muaj',
- 'week' => ':count javë',
- 'a_week' => ':count javë|:count javë',
- 'w' => ':count j.',
- 'day' => ':count ditë',
- 'a_day' => 'një ditë|:count ditë',
- 'd' => ':count d.',
- 'hour' => ':count orë',
- 'a_hour' => 'një orë|:count orë',
- 'h' => ':count o.',
- 'minute' => ':count minutë|:count minuta',
- 'a_minute' => 'një minutë|:count minuta',
- 'min' => ':count min.',
- 'second' => ':count sekondë|:count sekonda',
- 'a_second' => 'disa sekonda|:count sekonda',
- 's' => ':count s.',
- 'ago' => ':time më parë',
- 'from_now' => 'në :time',
- 'after' => ':time pas',
- 'before' => ':time para',
- 'diff_now' => 'tani',
- 'diff_yesterday' => 'dje',
- 'diff_tomorrow' => 'nesër',
- 'diff_before_yesterday' => 'pardje',
- 'diff_after_tomorrow' => 'pasnesër',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Sot në] LT',
- 'nextDay' => '[Nesër në] LT',
- 'nextWeek' => 'dddd [në] LT',
- 'lastDay' => '[Dje në] LT',
- 'lastWeek' => 'dddd [e kaluar në] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'meridiem' => ['PD', 'MD'],
- 'months' => ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik', 'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
- 'months_short' => ['jan', 'shk', 'mar', 'pri', 'maj', 'qer', 'kor', 'gus', 'sht', 'tet', 'nën', 'dhj'],
- 'weekdays' => ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte', 'e premte', 'e shtunë'],
- 'weekdays_short' => ['die', 'hën', 'mar', 'mër', 'enj', 'pre', 'sht'],
- 'weekdays_min' => ['d', 'h', 'ma', 'më', 'e', 'p', 'sh'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' dhe '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sq.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sq.php', [
- 'formats' => [
- 'L' => 'D.M.YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sq.php', [
- 'formats' => [
- 'L' => 'D.M.YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - shaishavgandhi05
- * - Serhan Apaydın
- * - JD Isaacks
- * - Glavić
- * - Milos Sakovic
- */
-return [
- 'year' => ':count godina|:count godine|:count godina',
- 'y' => ':count g.',
- 'month' => ':count mesec|:count meseca|:count meseci',
- 'm' => ':count mj.',
- 'week' => ':count nedelja|:count nedelje|:count nedelja',
- 'w' => ':count ned.',
- 'day' => ':count dan|:count dana|:count dana',
- 'd' => ':count d.',
- 'hour' => ':count sat|:count sata|:count sati',
- 'h' => ':count č.',
- 'minute' => ':count minut|:count minuta |:count minuta',
- 'min' => ':count min.',
- 'second' => ':count sekund|:count sekunde|:count sekunde',
- 's' => ':count sek.',
- 'ago' => 'pre :time',
- 'from_now' => 'za :time',
- 'after' => 'nakon :time',
- 'before' => 'pre :time',
-
- 'year_from_now' => ':count godinu|:count godine|:count godina',
- 'year_ago' => ':count godinu|:count godine|:count godina',
- 'week_from_now' => ':count nedelju|:count nedelje|:count nedelja',
- 'week_ago' => ':count nedelju|:count nedelje|:count nedelja',
-
- 'diff_now' => 'upravo sada',
- 'diff_yesterday' => 'juče',
- 'diff_tomorrow' => 'sutra',
- 'diff_before_yesterday' => 'prekjuče',
- 'diff_after_tomorrow' => 'preksutra',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[danas u] LT',
- 'nextDay' => '[sutra u] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[у недељу у] LT';
- case 3:
- return '[у среду у] LT';
- case 6:
- return '[у суботу у] LT';
- default:
- return '[у] dddd [у] LT';
- }
- },
- 'lastDay' => '[juče u] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[прошле недеље у] LT';
- case 1:
- return '[прошлог понедељка у] LT';
- case 2:
- return '[прошлог уторка у] LT';
- case 3:
- return '[прошле среде у] LT';
- case 4:
- return '[прошлог четвртка у] LT';
- case 5:
- return '[прошлог петка у] LT';
- default:
- return '[прошле суботе у] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
- 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],
- 'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
- 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'],
- 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' i '],
- 'meridiem' => ['пре подне', 'по подне'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Josh Soref
- * - François B
- * - shaishavgandhi05
- * - Serhan Apaydın
- * - JD Isaacks
- * - Glavić
- * - Nikola Zeravcic
- * - Milos Sakovic
- */
-return [
- 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
- 'y' => ':count г.',
- 'month' => '{1}:count месец|{2,3,4}:count месеца|[0,Inf[:count месеци',
- 'm' => ':count м.',
- 'week' => '{1}:count недеља|{2,3,4}:count недеље|[0,Inf[:count недеља',
- 'w' => ':count нед.',
- 'day' => '{1,21,31}:count дан|[0,Inf[:count дана',
- 'd' => ':count д.',
- 'hour' => '{1,21}:count сат|{2,3,4,22,23,24}:count сата|[0,Inf[:count сати',
- 'h' => ':count ч.',
- 'minute' => '{1,21,31,41,51}:count минут|[0,Inf[:count минута',
- 'min' => ':count мин.',
- 'second' => '{1,21,31,41,51}:count секунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count секунде|[0,Inf[:count секунди',
- 's' => ':count сек.',
- 'ago' => 'пре :time',
- 'from_now' => 'за :time',
- 'after' => ':time након',
- 'before' => ':time пре',
- 'year_from_now' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
- 'year_ago' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
- 'week_from_now' => '{1}:count недељу|{2,3,4}:count недеље|[0,Inf[:count недеља',
- 'week_ago' => '{1}:count недељу|{2,3,4}:count недеље|[0,Inf[:count недеља',
- 'diff_now' => 'управо сада',
- 'diff_yesterday' => 'јуче',
- 'diff_tomorrow' => 'сутра',
- 'diff_before_yesterday' => 'прекјуче',
- 'diff_after_tomorrow' => 'прекосутра',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[данас у] LT',
- 'nextDay' => '[сутра у] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[у недељу у] LT';
- case 3:
- return '[у среду у] LT';
- case 6:
- return '[у суботу у] LT';
- default:
- return '[у] dddd [у] LT';
- }
- },
- 'lastDay' => '[јуче у] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[прошле недеље у] LT';
- case 1:
- return '[прошлог понедељка у] LT';
- case 2:
- return '[прошлог уторка у] LT';
- case 3:
- return '[прошле среде у] LT';
- case 4:
- return '[прошлог четвртка у] LT';
- case 5:
- return '[прошлог петка у] LT';
- default:
- return '[прошле суботе у] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
- 'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
- 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
- 'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
- 'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' и '],
- 'meridiem' => ['АМ', 'ПМ'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sr_Cyrl.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D.M.yy.',
- 'LL' => 'DD.MM.YYYY.',
- 'LLL' => 'DD. MMMM YYYY. HH:mm',
- 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
- ],
- 'weekdays' => ['недјеља', 'понедељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
- 'weekdays_short' => ['нед.', 'пон.', 'ут.', 'ср.', 'чет.', 'пет.', 'суб.'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Glavić
- * - Milos Sakovic
- */
-return [
- 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
- 'y' => ':count г.',
- 'month' => '{1}:count мјесец|{2,3,4}:count мјесеца|[0,Inf[:count мјесеци',
- 'm' => ':count мј.',
- 'week' => '{1}:count недјеља|{2,3,4}:count недјеље|[0,Inf[:count недјеља',
- 'w' => ':count нед.',
- 'day' => '{1,21,31}:count дан|[0,Inf[:count дана',
- 'd' => ':count д.',
- 'hour' => '{1,21}:count сат|{2,3,4,22,23,24}:count сата|[0,Inf[:count сати',
- 'h' => ':count ч.',
- 'minute' => '{1,21,31,41,51}:count минут|[0,Inf[:count минута',
- 'min' => ':count мин.',
- 'second' => '{1,21,31,41,51}:count секунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count секунде|[0,Inf[:count секунди',
- 's' => ':count сек.',
- 'ago' => 'прије :time',
- 'from_now' => 'за :time',
- 'after' => ':time након',
- 'before' => ':time прије',
-
- 'year_from_now' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
- 'year_ago' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
-
- 'week_from_now' => '{1}:count недјељу|{2,3,4}:count недјеље|[0,Inf[:count недјеља',
- 'week_ago' => '{1}:count недјељу|{2,3,4}:count недјеље|[0,Inf[:count недјеља',
-
- 'diff_now' => 'управо сада',
- 'diff_yesterday' => 'јуче',
- 'diff_tomorrow' => 'сутра',
- 'diff_before_yesterday' => 'прекјуче',
- 'diff_after_tomorrow' => 'прекосјутра',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM YYYY',
- 'LLL' => 'D. MMMM YYYY H:mm',
- 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[данас у] LT',
- 'nextDay' => '[сутра у] LT',
- 'nextWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[у недељу у] LT';
- case 3:
- return '[у среду у] LT';
- case 6:
- return '[у суботу у] LT';
- default:
- return '[у] dddd [у] LT';
- }
- },
- 'lastDay' => '[јуче у] LT',
- 'lastWeek' => function (\Carbon\CarbonInterface $date) {
- switch ($date->dayOfWeek) {
- case 0:
- return '[прошле недеље у] LT';
- case 1:
- return '[прошлог понедељка у] LT';
- case 2:
- return '[прошлог уторка у] LT';
- case 3:
- return '[прошле среде у] LT';
- case 4:
- return '[прошлог четвртка у] LT';
- case 5:
- return '[прошлог петка у] LT';
- default:
- return '[прошле суботе у] LT';
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
- 'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
- 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
- 'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
- 'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' и '],
- 'meridiem' => ['АМ', 'ПМ'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sr_Cyrl_BA.php', [
- 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sr_Latn.php', [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D.M.yy.',
- 'LL' => 'DD.MM.YYYY.',
- 'LLL' => 'DD. MMMM YYYY. HH:mm',
- 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
- ],
- 'weekdays' => ['nedjelja', 'ponedeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
- 'weekdays_short' => ['ned.', 'pon.', 'ut.', 'sr.', 'čet.', 'pet.', 'sub.'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - Glavić
- * - Milos Sakovic
- */
-return array_replace_recursive(require __DIR__.'/sr.php', [
- 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
- 'week' => ':count nedjelja|:count nedjelje|:count nedjelja',
- 'second' => ':count sekund|:count sekunde|:count sekundi',
- 'ago' => 'prije :time',
- 'from_now' => 'za :time',
- 'after' => ':time nakon',
- 'before' => ':time prije',
- 'week_from_now' => ':count nedjelju|:count nedjelje|:count nedjelja',
- 'week_ago' => ':count nedjelju|:count nedjelje|:count nedjelja',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sr_Latn_BA.php', [
- 'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sr_Latn_ME.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - sr_YU, sr_CS locale Danilo Segan bug-glibc-locales@gnu.org
- */
-return require __DIR__.'/sr_Cyrl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'ss');
-
-/*
- * Authors:
- * - François B
- * - Nicolai Davies
- */
-return [
- 'year' => 'umnyaka|:count iminyaka',
- 'month' => 'inyanga|:count tinyanga',
- 'week' => ':count liviki|:count emaviki',
- 'day' => 'lilanga|:count emalanga',
- 'hour' => 'lihora|:count emahora',
- 'minute' => 'umzuzu|:count emizuzu',
- 'second' => 'emizuzwana lomcane|:count mzuzwana',
- 'ago' => 'wenteka nga :time',
- 'from_now' => 'nga :time',
- 'diff_yesterday' => 'Itolo',
- 'diff_tomorrow' => 'Kusasa',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm A',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
- ],
- 'calendar' => [
- 'sameDay' => '[Namuhla nga] LT',
- 'nextDay' => '[Kusasa nga] LT',
- 'nextWeek' => 'dddd [nga] LT',
- 'lastDay' => '[Itolo nga] LT',
- 'lastWeek' => 'dddd [leliphelile] [nga] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- $lastDigit = $number % 10;
-
- return $number.(
- (~~($number % 100 / 10) === 1) ? 'e' : (
- ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e'
- )
- );
- },
- 'meridiem' => function ($hour) {
- if ($hour < 11) {
- return 'ekuseni';
- }
- if ($hour < 15) {
- return 'emini';
- }
- if ($hour < 19) {
- return 'entsambama';
- }
-
- return 'ebusuku';
- },
- 'months' => ['Bhimbidvwane', 'Indlovana', 'Indlov\'lenkhulu', 'Mabasa', 'Inkhwekhweti', 'Inhlaba', 'Kholwane', 'Ingci', 'Inyoni', 'Imphala', 'Lweti', 'Ingongoni'],
- 'months_short' => ['Bhi', 'Ina', 'Inu', 'Mab', 'Ink', 'Inh', 'Kho', 'Igc', 'Iny', 'Imp', 'Lwe', 'Igo'],
- 'weekdays' => ['Lisontfo', 'Umsombuluko', 'Lesibili', 'Lesitsatfu', 'Lesine', 'Lesihlanu', 'Umgcibelo'],
- 'weekdays_short' => ['Lis', 'Umb', 'Lsb', 'Les', 'Lsi', 'Lsh', 'Umg'],
- 'weekdays_min' => ['Li', 'Us', 'Lb', 'Lt', 'Ls', 'Lh', 'Ug'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/ss.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/st_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Pherekgong', 'Hlakola', 'Tlhakubele', 'Mmese', 'Motsheanong', 'Phupjane', 'Phupu', 'Phato', 'Leotse', 'Mphalane', 'Pudungwana', 'Tshitwe'],
- 'months_short' => ['Phe', 'Hla', 'TlH', 'Mme', 'Mot', 'Jan', 'Upu', 'Pha', 'Leo', 'Mph', 'Pud', 'Tsh'],
- 'weekdays' => ['Sontaha', 'Mantaha', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Moqebelo'],
- 'weekdays_short' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'],
- 'weekdays_min' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'],
- 'day_of_first_week_of_year' => 1,
-
- 'week' => ':count Sontaha', // less reliable
- 'w' => ':count Sontaha', // less reliable
- 'a_week' => ':count Sontaha', // less reliable
-
- 'day' => ':count letsatsi', // less reliable
- 'd' => ':count letsatsi', // less reliable
- 'a_day' => ':count letsatsi', // less reliable
-
- 'hour' => ':count sešupanako', // less reliable
- 'h' => ':count sešupanako', // less reliable
- 'a_hour' => ':count sešupanako', // less reliable
-
- 'minute' => ':count menyane', // less reliable
- 'min' => ':count menyane', // less reliable
- 'a_minute' => ':count menyane', // less reliable
-
- 'second' => ':count thusa', // less reliable
- 's' => ':count thusa', // less reliable
- 'a_second' => ':count thusa', // less reliable
-
- 'year' => ':count selemo',
- 'y' => ':count selemo',
- 'a_year' => ':count selemo',
-
- 'month' => ':count kgwedi',
- 'm' => ':count kgwedi',
- 'a_month' => ':count kgwedi',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - François B
- * - Kristoffer Snabb
- * - JD Isaacks
- * - Jens Herlevsen
- * - Nightpine
- */
-return [
- 'year' => ':count år',
- 'a_year' => 'ett år|:count år',
- 'y' => ':count år',
- 'month' => ':count månad|:count månader',
- 'a_month' => 'en månad|:count månader',
- 'm' => ':count mån.',
- 'week' => ':count vecka|:count veckor',
- 'a_week' => 'en vecka|:count veckor',
- 'w' => ':count v.',
- 'day' => ':count dag|:count dagar',
- 'a_day' => 'en dag|:count dagar',
- 'd' => ':count d.',
- 'hour' => ':count timme|:count timmar',
- 'a_hour' => 'en timme|:count timmar',
- 'h' => ':count t.',
- 'minute' => ':count minut|:count minuter',
- 'a_minute' => 'en minut|:count minuter',
- 'min' => ':count min.',
- 'second' => ':count sekund|:count sekunder',
- 'a_second' => 'några sekunder|:count sekunder',
- 's' => ':count s.',
- 'ago' => 'för :time sedan',
- 'from_now' => 'om :time',
- 'after' => ':time efter',
- 'before' => ':time före',
- 'diff_yesterday' => 'Igår',
- 'diff_tomorrow' => 'Imorgon',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY [kl.] HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY [kl.] HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Idag] LT',
- 'nextDay' => '[Imorgon] LT',
- 'nextWeek' => '[På] dddd LT',
- 'lastDay' => '[Igår] LT',
- 'lastWeek' => '[I] dddd[s] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- $lastDigit = $number % 10;
-
- return $number.(
- (~~($number % 100 / 10) === 1) ? 'e' : (
- ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e'
- )
- );
- },
- 'months' => ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],
- 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
- 'weekdays' => ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'],
- 'weekdays_short' => ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
- 'weekdays_min' => ['sö', 'må', 'ti', 'on', 'to', 'fr', 'lö'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' och '],
- 'meridiem' => ['fm', 'em'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sv.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sv.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/sv.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - leyluj
- * - Josh Soref
- * - ryanhart2
- */
-return [
- 'year' => 'mwaka :count|miaka :count',
- 'a_year' => 'mwaka mmoja|miaka :count',
- 'y' => 'mwaka :count|miaka :count',
- 'month' => 'mwezi :count|miezi :count',
- 'a_month' => 'mwezi mmoja|miezi :count',
- 'm' => 'mwezi :count|miezi :count',
- 'week' => 'wiki :count',
- 'a_week' => 'wiki mmoja|wiki :count',
- 'w' => 'w. :count',
- 'day' => 'siku :count',
- 'a_day' => 'siku moja|masiku :count',
- 'd' => 'si. :count',
- 'hour' => 'saa :count|masaa :count',
- 'a_hour' => 'saa limoja|masaa :count',
- 'h' => 'saa :count|masaa :count',
- 'minute' => 'dakika :count',
- 'a_minute' => 'dakika moja|dakika :count',
- 'min' => 'd. :count',
- 'second' => 'sekunde :count',
- 'a_second' => 'hivi punde|sekunde :count',
- 's' => 'se. :count',
- 'ago' => 'tokea :time',
- 'from_now' => ':time baadaye',
- 'after' => ':time baada',
- 'before' => ':time kabla',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[leo saa] LT',
- 'nextDay' => '[kesho saa] LT',
- 'nextWeek' => '[wiki ijayo] dddd [saat] LT',
- 'lastDay' => '[jana] LT',
- 'lastWeek' => '[wiki iliyopita] dddd [saat] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Jpl', 'Jtat', 'Jnne', 'Jtan', 'Alh', 'Ijm', 'Jmos'],
- 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' na '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sw.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kamusi Project Martin Benjamin locales@kamusi.org
- */
-return array_replace_recursive(require __DIR__.'/sw.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
- 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['asubuhi', 'alasiri'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kamusi Project Martin Benjamin locales@kamusi.org
- */
-return array_replace_recursive(require __DIR__.'/sw.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
- 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['asubuhi', 'alasiri'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/sw.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/szl_PL.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - szl_PL locale Przemyslaw Buczkowski libc-alpha@sourceware.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['styczyń', 'luty', 'merc', 'kwjeciyń', 'moj', 'czyrwjyń', 'lipjyń', 'siyrpjyń', 'wrzesiyń', 'październik', 'listopad', 'grudziyń'],
- 'months_short' => ['sty', 'lut', 'mer', 'kwj', 'moj', 'czy', 'lip', 'siy', 'wrz', 'paź', 'lis', 'gru'],
- 'weekdays' => ['niydziela', 'pyńdziŏek', 'wtŏrek', 'strzŏda', 'sztwortek', 'pjōntek', 'sobŏta'],
- 'weekdays_short' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'],
- 'weekdays_min' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count rok',
- 'y' => ':count rok',
- 'a_year' => ':count rok',
-
- 'month' => ':count mjeśůnc',
- 'm' => ':count mjeśůnc',
- 'a_month' => ':count mjeśůnc',
-
- 'week' => ':count Tydźyń',
- 'w' => ':count Tydźyń',
- 'a_week' => ':count Tydźyń',
-
- 'day' => ':count dźyń',
- 'd' => ':count dźyń',
- 'a_day' => ':count dźyń',
-
- 'hour' => ':count godzina',
- 'h' => ':count godzina',
- 'a_hour' => ':count godzina',
-
- 'minute' => ':count Minuta',
- 'min' => ':count Minuta',
- 'a_minute' => ':count Minuta',
-
- 'second' => ':count Sekůnda',
- 's' => ':count Sekůnda',
- 'a_second' => ':count Sekůnda',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - François B
- * - JD Isaacks
- */
-return [
- 'year' => ':count வருடம்|:count ஆண்டுகள்',
- 'a_year' => 'ஒரு வருடம்|:count ஆண்டுகள்',
- 'y' => ':count வருட.|:count ஆண்.',
- 'month' => ':count மாதம்|:count மாதங்கள்',
- 'a_month' => 'ஒரு மாதம்|:count மாதங்கள்',
- 'm' => ':count மாத.',
- 'week' => ':count வாரம்|:count வாரங்கள்',
- 'a_week' => 'ஒரு வாரம்|:count வாரங்கள்',
- 'w' => ':count வார.',
- 'day' => ':count நாள்|:count நாட்கள்',
- 'a_day' => 'ஒரு நாள்|:count நாட்கள்',
- 'd' => ':count நாள்|:count நாட்.',
- 'hour' => ':count மணி நேரம்|:count மணி நேரம்',
- 'a_hour' => 'ஒரு மணி நேரம்|:count மணி நேரம்',
- 'h' => ':count மணி.',
- 'minute' => ':count நிமிடம்|:count நிமிடங்கள்',
- 'a_minute' => 'ஒரு நிமிடம்|:count நிமிடங்கள்',
- 'min' => ':count நிமி.',
- 'second' => ':count சில விநாடிகள்|:count விநாடிகள்',
- 'a_second' => 'ஒரு சில விநாடிகள்|:count விநாடிகள்',
- 's' => ':count விநா.',
- 'ago' => ':time முன்',
- 'from_now' => ':time இல்',
- 'diff_yesterday' => 'நேற்று',
- 'diff_tomorrow' => 'நாளை',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[இன்று] LT',
- 'nextDay' => '[நாளை] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[நேற்று] LT',
- 'lastWeek' => '[கடந்த வாரம்] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberவது',
- 'meridiem' => function ($hour) {
- if ($hour < 2) {
- return ' யாமம்';
- }
- if ($hour < 6) {
- return ' வைகறை';
- }
- if ($hour < 10) {
- return ' காலை';
- }
- if ($hour < 14) {
- return ' நண்பகல்';
- }
- if ($hour < 18) {
- return ' எற்பாடு';
- }
- if ($hour < 22) {
- return ' மாலை';
- }
-
- return ' யாமம்';
- },
- 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
- 'months_short' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
- 'weekdays' => ['ஞாயிற்றுக்கிழமை', 'திங்கட்கிழமை', 'செவ்வாய்கிழமை', 'புதன்கிழமை', 'வியாழக்கிழமை', 'வெள்ளிக்கிழமை', 'சனிக்கிழமை'],
- 'weekdays_short' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
- 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' மற்றும் '],
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ta.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
- 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
- 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
- 'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['காலை', 'மாலை'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - J.Yogaraj 94-777-315206 yogaraj.ubuntu@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/ta.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
- 'months_short' => ['ஜன', 'பிப்', 'மார்', 'ஏப்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக', 'செப்', 'அக்', 'நவ', 'டிச'],
- 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
- 'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['காலை', 'மாலை'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ta.php', [
- 'formats' => [
- 'LT' => 'a h:mm',
- 'LTS' => 'a h:mm:ss',
- 'L' => 'D/M/yy',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM, YYYY, a h:mm',
- 'LLLL' => 'dddd, D MMMM, YYYY, a h:mm',
- ],
- 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
- 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
- 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
- 'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'],
- 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'first_day_of_week' => 1,
- 'meridiem' => ['மு.ப', 'பி.ப'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ta.php', [
- 'formats' => [
- 'LT' => 'a h:mm',
- 'LTS' => 'a h:mm:ss',
- 'L' => 'D/M/yy',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM, YYYY, a h:mm',
- 'LLLL' => 'dddd, D MMMM, YYYY, a h:mm',
- ],
- 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
- 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
- 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
- 'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'],
- 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
- 'meridiem' => ['மு.ப', 'பி.ப'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/tcy_IN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IndLinux.org, Samsung Electronics Co., Ltd. alexey.merzlyakov@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['ಜನವರಿ', 'ಫೆಬ್ರುವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'],
- 'months_short' => ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ', 'ಜು', 'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
- 'weekdays' => ['ಐಥಾರ', 'ಸೋಮಾರ', 'ಅಂಗರೆ', 'ಬುಧಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರರ', 'ಶನಿವಾರ'],
- 'weekdays_short' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
- 'weekdays_min' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ಕಾಂಡೆ', 'ಬಯ್ಯ'],
-
- 'year' => ':count ನೀರ್', // less reliable
- 'y' => ':count ನೀರ್', // less reliable
- 'a_year' => ':count ನೀರ್', // less reliable
-
- 'month' => ':count ಮೀನ್', // less reliable
- 'm' => ':count ಮೀನ್', // less reliable
- 'a_month' => ':count ಮೀನ್', // less reliable
-
- 'day' => ':count ಸುಗ್ಗಿ', // less reliable
- 'd' => ':count ಸುಗ್ಗಿ', // less reliable
- 'a_day' => ':count ಸುಗ್ಗಿ', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kunal Marwaha
- * - Josh Soref
- * - François B
- * - kc
- */
-return [
- 'year' => ':count సంవత్సరం|:count సంవత్సరాలు',
- 'a_year' => 'ఒక సంవత్సరం|:count సంవత్సరాలు',
- 'y' => ':count సం.',
- 'month' => ':count నెల|:count నెలలు',
- 'a_month' => 'ఒక నెల|:count నెలలు',
- 'm' => ':count నెల|:count నెల.',
- 'week' => ':count వారం|:count వారాలు',
- 'a_week' => 'ఒక వారం|:count వారాలు',
- 'w' => ':count వార.|:count వారా.',
- 'day' => ':count రోజు|:count రోజులు',
- 'a_day' => 'ఒక రోజు|:count రోజులు',
- 'd' => ':count రోజు|:count రోజు.',
- 'hour' => ':count గంట|:count గంటలు',
- 'a_hour' => 'ఒక గంట|:count గంటలు',
- 'h' => ':count గం.',
- 'minute' => ':count నిమిషం|:count నిమిషాలు',
- 'a_minute' => 'ఒక నిమిషం|:count నిమిషాలు',
- 'min' => ':count నిమి.',
- 'second' => ':count సెకను|:count సెకన్లు',
- 'a_second' => 'కొన్ని క్షణాలు|:count సెకన్లు',
- 's' => ':count సెక.',
- 'ago' => ':time క్రితం',
- 'from_now' => ':time లో',
- 'diff_yesterday' => 'నిన్న',
- 'diff_tomorrow' => 'రేపు',
- 'formats' => [
- 'LT' => 'A h:mm',
- 'LTS' => 'A h:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, A h:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[నేడు] LT',
- 'nextDay' => '[రేపు] LT',
- 'nextWeek' => 'dddd, LT',
- 'lastDay' => '[నిన్న] LT',
- 'lastWeek' => '[గత] dddd, LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberవ',
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'రాత్రి';
- }
- if ($hour < 10) {
- return 'ఉదయం';
- }
- if ($hour < 17) {
- return 'మధ్యాహ్నం';
- }
- if ($hour < 20) {
- return 'సాయంత్రం';
- }
-
- return ' రాత్రి';
- },
- 'months' => ['జనవరి', 'ఫిబ్రవరి', 'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్', 'జూలై', 'ఆగస్టు', 'సెప్టెంబర్', 'అక్టోబర్', 'నవంబర్', 'డిసెంబర్'],
- 'months_short' => ['జన.', 'ఫిబ్ర.', 'మార్చి', 'ఏప్రి.', 'మే', 'జూన్', 'జూలై', 'ఆగ.', 'సెప్.', 'అక్టో.', 'నవ.', 'డిసె.'],
- 'weekdays' => ['ఆదివారం', 'సోమవారం', 'మంగళవారం', 'బుధవారం', 'గురువారం', 'శుక్రవారం', 'శనివారం'],
- 'weekdays_short' => ['ఆది', 'సోమ', 'మంగళ', 'బుధ', 'గురు', 'శుక్ర', 'శని'],
- 'weekdays_min' => ['ఆ', 'సో', 'మం', 'బు', 'గు', 'శు', 'శ'],
- 'list' => ', ',
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'weekend' => [0, 0],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/te.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ta.php', [
- 'meridiem' => ['Taparachu', 'Ebongi'],
- 'weekdays' => ['Nakaejuma', 'Nakaebarasa', 'Nakaare', 'Nakauni', 'Nakaung’on', 'Nakakany', 'Nakasabiti'],
- 'weekdays_short' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
- 'weekdays_min' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
- 'months' => ['Orara', 'Omuk', 'Okwamg’', 'Odung’el', 'Omaruk', 'Omodok’king’ol', 'Ojola', 'Opedel', 'Osokosokoma', 'Otibar', 'Olabor', 'Opoo'],
- 'months_short' => ['Rar', 'Muk', 'Kwa', 'Dun', 'Mar', 'Mod', 'Jol', 'Ped', 'Sok', 'Tib', 'Lab', 'Poo'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/teo.php', [
- 'first_day_of_week' => 0,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'tet');
-
-/*
- * Authors:
- * - Joshua Brooks
- * - François B
- */
-return [
- 'year' => 'tinan :count',
- 'a_year' => 'tinan ida|tinan :count',
- 'month' => 'fulan :count',
- 'a_month' => 'fulan ida|fulan :count',
- 'week' => 'semana :count',
- 'a_week' => 'semana ida|semana :count',
- 'day' => 'loron :count',
- 'a_day' => 'loron ida|loron :count',
- 'hour' => 'oras :count',
- 'a_hour' => 'oras ida|oras :count',
- 'minute' => 'minutu :count',
- 'a_minute' => 'minutu ida|minutu :count',
- 'second' => 'segundu :count',
- 'a_second' => 'segundu balun|segundu :count',
- 'ago' => ':time liuba',
- 'from_now' => 'iha :time',
- 'diff_yesterday' => 'Horiseik',
- 'diff_tomorrow' => 'Aban',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Ohin iha] LT',
- 'nextDay' => '[Aban iha] LT',
- 'nextWeek' => 'dddd [iha] LT',
- 'lastDay' => '[Horiseik iha] LT',
- 'lastWeek' => 'dddd [semana kotuk] [iha] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':numberº',
- 'months' => ['Janeiru', 'Fevereiru', 'Marsu', 'Abril', 'Maiu', 'Juñu', 'Jullu', 'Agustu', 'Setembru', 'Outubru', 'Novembru', 'Dezembru'],
- 'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
- 'weekdays' => ['Domingu', 'Segunda', 'Tersa', 'Kuarta', 'Kinta', 'Sesta', 'Sabadu'],
- 'weekdays_short' => ['Dom', 'Seg', 'Ters', 'Kua', 'Kint', 'Sest', 'Sab'],
- 'weekdays_min' => ['Do', 'Seg', 'Te', 'Ku', 'Ki', 'Ses', 'Sa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'tg');
-
-/*
- * Authors:
- * - Orif N. Jr
- */
-return [
- 'year' => 'як сол|:count сол',
- 'month' => 'як моҳ|:count моҳ',
- 'week' => 'як ҳафта|:count ҳафта',
- 'day' => 'як рӯз|:count рӯз',
- 'hour' => 'як соат|:count соат',
- 'minute' => 'як дақиқа|:count дақиқа',
- 'second' => 'якчанд сония|:count сония',
- 'ago' => ':time пеш',
- 'from_now' => 'баъди :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Имрӯз соати] LT',
- 'nextDay' => '[Пагоҳ соати] LT',
- 'nextWeek' => 'dddd[и] [ҳафтаи оянда соати] LT',
- 'lastDay' => '[Дирӯз соати] LT',
- 'lastWeek' => 'dddd[и] [ҳафтаи гузашта соати] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number) {
- if ($number === 0) { // special case for zero
- return "$number-ıncı";
- }
-
- static $suffixes = [
- 0 => '-ум',
- 1 => '-ум',
- 2 => '-юм',
- 3 => '-юм',
- 4 => '-ум',
- 5 => '-ум',
- 6 => '-ум',
- 7 => '-ум',
- 8 => '-ум',
- 9 => '-ум',
- 10 => '-ум',
- 12 => '-ум',
- 13 => '-ум',
- 20 => '-ум',
- 30 => '-юм',
- 40 => '-ум',
- 50 => '-ум',
- 60 => '-ум',
- 70 => '-ум',
- 80 => '-ум',
- 90 => '-ум',
- 100 => '-ум',
- ];
-
- return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
- },
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'шаб';
- }
- if ($hour < 11) {
- return 'субҳ';
- }
- if ($hour < 16) {
- return 'рӯз';
- }
- if ($hour < 19) {
- return 'бегоҳ';
- }
-
- return 'шаб';
- },
- 'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'],
- 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'weekdays' => ['якшанбе', 'душанбе', 'сешанбе', 'чоршанбе', 'панҷшанбе', 'ҷумъа', 'шанбе'],
- 'weekdays_short' => ['яшб', 'дшб', 'сшб', 'чшб', 'пшб', 'ҷум', 'шнб'],
- 'weekdays_min' => ['яш', 'дш', 'сш', 'чш', 'пш', 'ҷм', 'шб'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' ва '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/tg.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Nate Whittaker
- * - John MacAslan
- * - Chanintorn Asavavichairoj
- * - JD Isaacks
- * - ROKAISAKKON
- * - RO'KAISAKKON
- * - Andreas Möller
- */
-return [
- 'year' => ':count ปี',
- 'y' => ':count ปี',
- 'month' => ':count เดือน',
- 'm' => ':count เดือน',
- 'week' => ':count สัปดาห์',
- 'w' => ':count สัปดาห์',
- 'day' => ':count วัน',
- 'd' => ':count วัน',
- 'hour' => ':count ชั่วโมง',
- 'h' => ':count ชั่วโมง',
- 'minute' => ':count นาที',
- 'min' => ':count นาที',
- 'second' => '{1}ไม่กี่วินาที|]1,Inf[:count วินาที',
- 's' => ':count วินาที',
- 'ago' => ':timeที่แล้ว',
- 'from_now' => 'อีก :time',
- 'after' => ':timeหลังจากนี้',
- 'before' => ':timeก่อน',
- 'formats' => [
- 'LT' => 'H:mm',
- 'LTS' => 'H:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY เวลา H:mm',
- 'LLLL' => 'วันddddที่ D MMMM YYYY เวลา H:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[วันนี้ เวลา] LT',
- 'nextDay' => '[พรุ่งนี้ เวลา] LT',
- 'nextWeek' => 'dddd[หน้า เวลา] LT',
- 'lastDay' => '[เมื่อวานนี้ เวลา] LT',
- 'lastWeek' => '[วัน]dddd[ที่แล้ว เวลา] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ก่อนเที่ยง', 'หลังเที่ยง'],
- 'months' => ['มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'],
- 'months_short' => ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],
- 'weekdays' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์'],
- 'weekdays_short' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัส', 'ศุกร์', 'เสาร์'],
- 'weekdays_min' => ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
- 'list' => [', ', ' และ '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/th.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/the_NP.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Chitwanix OS Development info@chitwanix.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'dddd DD MMM YYYY',
- ],
- 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
- 'weekdays' => ['आइतबार', 'सोमबार', 'मंगलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'],
- 'weekdays_short' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'],
- 'weekdays_min' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ti_ER.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
- 'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'],
- 'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
- 'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
- 'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
-
- 'year' => ':count ዓመት',
- 'y' => ':count ዓመት',
- 'a_year' => ':count ዓመት',
-
- 'month' => 'ወርሒ :count',
- 'm' => 'ወርሒ :count',
- 'a_month' => 'ወርሒ :count',
-
- 'week' => ':count ሰሙን',
- 'w' => ':count ሰሙን',
- 'a_week' => ':count ሰሙን',
-
- 'day' => ':count መዓልቲ',
- 'd' => ':count መዓልቲ',
- 'a_day' => ':count መዓልቲ',
-
- 'hour' => ':count ሰዓት',
- 'h' => ':count ሰዓት',
- 'a_hour' => ':count ሰዓት',
-
- 'minute' => ':count ደቒቕ',
- 'min' => ':count ደቒቕ',
- 'a_minute' => ':count ደቒቕ',
-
- 'second' => ':count ሰከንድ',
- 's' => ':count ሰከንድ',
- 'a_second' => ':count ሰከንድ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
- 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
- 'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
- 'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
- 'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/tig_ER.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
- 'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'],
- 'weekdays' => ['ሰንበት ዓባይ', 'ሰኖ', 'ታላሸኖ', 'ኣረርባዓ', 'ከሚሽ', 'ጅምዓት', 'ሰንበት ንኢሽ'],
- 'weekdays_short' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'],
- 'weekdays_min' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ቀደም ሰር ምዕል', 'ሓቆ ሰር ምዕል'],
-
- 'year' => ':count ማይ', // less reliable
- 'y' => ':count ማይ', // less reliable
- 'a_year' => ':count ማይ', // less reliable
-
- 'month' => ':count ሸምሽ', // less reliable
- 'm' => ':count ሸምሽ', // less reliable
- 'a_month' => ':count ሸምሽ', // less reliable
-
- 'week' => ':count ሰቡዕ', // less reliable
- 'w' => ':count ሰቡዕ', // less reliable
- 'a_week' => ':count ሰቡዕ', // less reliable
-
- 'day' => ':count ዎሮ', // less reliable
- 'd' => ':count ዎሮ', // less reliable
- 'a_day' => ':count ዎሮ', // less reliable
-
- 'hour' => ':count ሰዓት', // less reliable
- 'h' => ':count ሰዓት', // less reliable
- 'a_hour' => ':count ሰዓት', // less reliable
-
- 'minute' => ':count ካልኣይት', // less reliable
- 'min' => ':count ካልኣይት', // less reliable
- 'a_minute' => ':count ካልኣይት', // less reliable
-
- 'second' => ':count ካልኣይ',
- 's' => ':count ካልኣይ',
- 'a_second' => ':count ካልኣይ',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/tk_TM.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ghorban M. Tavakoly Pablo Saratxaga & Ghorban M. Tavakoly pablo@walon.org & gmt314@yahoo.com
- * - SuperManPHP
- */
-$transformDiff = function ($input) {
- return strtr($input, [
- 'sekunt' => 'sekunt',
- 'hepde' => 'hepde',
- ]);
-};
-
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Ýanwar', 'Fewral', 'Mart', 'Aprel', 'Maý', 'Iýun', 'Iýul', 'Awgust', 'Sentýabr', 'Oktýabr', 'Noýabr', 'Dekabr'],
- 'months_short' => ['Ýan', 'Few', 'Mar', 'Apr', 'Maý', 'Iýn', 'Iýl', 'Awg', 'Sen', 'Okt', 'Noý', 'Dek'],
- 'weekdays' => ['Duşenbe', 'Sişenbe', 'Çarşenbe', 'Penşenbe', 'Anna', 'Şenbe', 'Ýekşenbe'],
- 'weekdays_short' => ['Duş', 'Siş', 'Çar', 'Pen', 'Ann', 'Şen', 'Ýek'],
- 'weekdays_min' => ['Duş', 'Siş', 'Çar', 'Pen', 'Ann', 'Şen', 'Ýek'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count ýyl',
- 'y' => ':count ýyl',
- 'a_year' => ':count ýyl',
-
- 'month' => 'aý :count',
- 'm' => 'aý :count',
- 'a_month' => 'aý :count',
-
- 'week' => ':count hepde',
- 'w' => ':count hepde',
- 'a_week' => ':count hepde',
-
- 'day' => ':count gün',
- 'd' => ':count gün',
- 'a_day' => ':count gün',
-
- 'hour' => ':count sagat',
- 'h' => ':count sagat',
- 'a_hour' => ':count sagat',
-
- 'minute' => ':count minut',
- 'min' => ':count minut',
- 'a_minute' => ':count minut',
-
- 'second' => ':count sekunt',
- 's' => ':count sekunt',
- 'a_second' => ':count sekunt',
-
- 'ago' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' ozal';
- },
- 'from_now' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' soňra';
- },
- 'after' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' soň';
- },
- 'before' => function ($time) use ($transformDiff) {
- return $transformDiff($time).' öň';
- },
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'tl');
-
-return [
- 'year' => ':count taon',
- 'a_year' => 'isang taon|:count taon',
- 'month' => ':count buwan',
- 'a_month' => 'isang buwan|:count buwan',
- 'week' => ':count linggo',
- 'a_week' => 'isang linggo|:count linggo',
- 'day' => ':count araw',
- 'a_day' => 'isang araw|:count araw',
- 'hour' => ':count oras',
- 'a_hour' => 'isang oras|:count oras',
- 'minute' => ':count minuto',
- 'a_minute' => 'isang minuto|:count minuto',
- 'min' => ':count min.',
- 'second' => ':count segundo',
- 'a_second' => 'ilang segundo|:count segundo',
- 's' => ':count seg.',
- 'ago' => ':time ang nakalipas',
- 'from_now' => 'sa loob ng :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'MM/D/YYYY',
- 'LL' => 'MMMM D, YYYY',
- 'LLL' => 'MMMM D, YYYY HH:mm',
- 'LLLL' => 'dddd, MMMM DD, YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => 'LT [ngayong araw]',
- 'nextDay' => '[Bukas ng] LT',
- 'nextWeek' => 'LT [sa susunod na] dddd',
- 'lastDay' => 'LT [kahapon]',
- 'lastWeek' => 'LT [noong nakaraang] dddd',
- 'sameElse' => 'L',
- ],
- 'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
- 'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
- 'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes', 'Sabado'],
- 'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
- 'weekdays_min' => ['Li', 'Lu', 'Ma', 'Mi', 'Hu', 'Bi', 'Sab'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' at '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Ian De La Cruz
- * - JD Isaacks
- */
-return require __DIR__.'/tl.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'tlh');
-
-/*
- * Authors:
- * - François B
- * - Serhan Apaydın
- * - Dominika
- */
-return [
- 'year' => 'wa’ DIS|:count DIS',
- 'month' => 'wa’ jar|:count jar',
- 'week' => 'wa’ hogh|:count hogh',
- 'day' => 'wa’ jaj|:count jaj',
- 'hour' => 'wa’ rep|:count rep',
- 'minute' => 'wa’ tup|:count tup',
- 'second' => 'puS lup|:count lup',
- 'ago' => function ($time) {
- $output = strtr($time, [
- 'jaj' => 'Hu’',
- 'jar' => 'wen',
- 'DIS' => 'ben',
- ]);
-
- return $output === $time ? "$time ret" : $output;
- },
- 'from_now' => function ($time) {
- $output = strtr($time, [
- 'jaj' => 'leS',
- 'jar' => 'waQ',
- 'DIS' => 'nem',
- ]);
-
- return $output === $time ? "$time pIq" : $output;
- },
- 'diff_yesterday' => 'wa’Hu’',
- 'diff_tomorrow' => 'wa’leS',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[DaHjaj] LT',
- 'nextDay' => '[wa’leS] LT',
- 'nextWeek' => 'LLL',
- 'lastDay' => '[wa’Hu’] LT',
- 'lastWeek' => 'LLL',
- 'sameElse' => 'L',
- ],
- 'ordinal' => ':number.',
- 'months' => ['tera’ jar wa’', 'tera’ jar cha’', 'tera’ jar wej', 'tera’ jar loS', 'tera’ jar vagh', 'tera’ jar jav', 'tera’ jar Soch', 'tera’ jar chorgh', 'tera’ jar Hut', 'tera’ jar wa’maH', 'tera’ jar wa’maH wa’', 'tera’ jar wa’maH cha’'],
- 'months_short' => ['jar wa’', 'jar cha’', 'jar wej', 'jar loS', 'jar vagh', 'jar jav', 'jar Soch', 'jar chorgh', 'jar Hut', 'jar wa’maH', 'jar wa’maH wa’', 'jar wa’maH cha’'],
- 'weekdays' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
- 'weekdays_short' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
- 'weekdays_min' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' ’ej '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/tn_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Ferikgong', 'Tlhakole', 'Mopitlwe', 'Moranang', 'Motsheganong', 'Seetebosigo', 'Phukwi', 'Phatwe', 'Lwetse', 'Diphalane', 'Ngwanatsele', 'Sedimonthole'],
- 'months_short' => ['Fer', 'Tlh', 'Mop', 'Mor', 'Mot', 'See', 'Phu', 'Pha', 'Lwe', 'Dip', 'Ngw', 'Sed'],
- 'weekdays' => ['laTshipi', 'Mosupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labotlhano', 'Lamatlhatso'],
- 'weekdays_short' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'],
- 'weekdays_min' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => 'dingwaga di le :count',
- 'y' => 'dingwaga di le :count',
- 'a_year' => 'dingwaga di le :count',
-
- 'month' => 'dikgwedi di le :count',
- 'm' => 'dikgwedi di le :count',
- 'a_month' => 'dikgwedi di le :count',
-
- 'week' => 'dibeke di le :count',
- 'w' => 'dibeke di le :count',
- 'a_week' => 'dibeke di le :count',
-
- 'day' => 'malatsi :count',
- 'd' => 'malatsi :count',
- 'a_day' => 'malatsi :count',
-
- 'hour' => 'diura di le :count',
- 'h' => 'diura di le :count',
- 'a_hour' => 'diura di le :count',
-
- 'minute' => 'metsotso e le :count',
- 'min' => 'metsotso e le :count',
- 'a_minute' => 'metsotso e le :count',
-
- 'second' => 'metsotswana e le :count',
- 's' => 'metsotswana e le :count',
- 'a_second' => 'metsotswana e le :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/to_TO.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - International Components for Unicode akhilesh.k@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'dddd DD MMM YYYY',
- ],
- 'months' => ['Sānuali', 'Fēpueli', 'Maʻasi', 'ʻEpeleli', 'Mē', 'Sune', 'Siulai', 'ʻAokosi', 'Sepitema', 'ʻOkatopa', 'Nōvema', 'Tīsema'],
- 'months_short' => ['Sān', 'Fēp', 'Maʻa', 'ʻEpe', 'Mē', 'Sun', 'Siu', 'ʻAok', 'Sep', 'ʻOka', 'Nōv', 'Tīs'],
- 'weekdays' => ['Sāpate', 'Mōnite', 'Tūsite', 'Pulelulu', 'Tuʻapulelulu', 'Falaite', 'Tokonaki'],
- 'weekdays_short' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
- 'weekdays_min' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
- 'meridiem' => ['hengihengi', 'efiafi'],
-
- 'year' => ':count fitu', // less reliable
- 'y' => ':count fitu', // less reliable
- 'a_year' => ':count fitu', // less reliable
-
- 'month' => ':count mahina', // less reliable
- 'm' => ':count mahina', // less reliable
- 'a_month' => ':count mahina', // less reliable
-
- 'week' => ':count Sapate', // less reliable
- 'w' => ':count Sapate', // less reliable
- 'a_week' => ':count Sapate', // less reliable
-
- 'day' => ':count ʻaho', // less reliable
- 'd' => ':count ʻaho', // less reliable
- 'a_day' => ':count ʻaho', // less reliable
-
- 'hour' => ':count houa',
- 'h' => ':count houa',
- 'a_hour' => ':count houa',
-
- 'minute' => ':count miniti',
- 'min' => ':count miniti',
- 'a_minute' => ':count miniti',
-
- 'second' => ':count sekoni',
- 's' => ':count sekoni',
- 'a_second' => ':count sekoni',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/tpi_PG.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Janueri', 'Februeri', 'Mas', 'Epril', 'Me', 'Jun', 'Julai', 'Ogas', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mas', 'Epr', 'Me', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Des'],
- 'weekdays' => ['Sande', 'Mande', 'Tunde', 'Trinde', 'Fonde', 'Fraide', 'Sarere'],
- 'weekdays_short' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'],
- 'weekdays_min' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['biknait', 'apinun'],
-
- 'year' => 'yia :count',
- 'y' => 'yia :count',
- 'a_year' => 'yia :count',
-
- 'month' => ':count mun',
- 'm' => ':count mun',
- 'a_month' => ':count mun',
-
- 'week' => ':count wik',
- 'w' => ':count wik',
- 'a_week' => ':count wik',
-
- 'day' => ':count de',
- 'd' => ':count de',
- 'a_day' => ':count de',
-
- 'hour' => ':count aua',
- 'h' => ':count aua',
- 'a_hour' => ':count aua',
-
- 'minute' => ':count minit',
- 'min' => ':count minit',
- 'a_minute' => ':count minit',
-
- 'second' => ':count namba tu',
- 's' => ':count namba tu',
- 'a_second' => ':count namba tu',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Josh Soref
- * - Alan Agius
- * - Erhan Gundogan
- * - François B
- * - JD Isaacks
- * - Murat Yüksel
- * - Baran Şengül
- * - Selami (selamialtin)
- */
-return [
- 'year' => ':count yıl',
- 'a_year' => '{1}bir yıl|]1,Inf[:count yıl',
- 'y' => ':countyıl',
- 'month' => ':count ay',
- 'a_month' => '{1}bir ay|]1,Inf[:count ay',
- 'm' => ':countay',
- 'week' => ':count hafta',
- 'a_week' => '{1}bir hafta|]1,Inf[:count hafta',
- 'w' => ':counth',
- 'day' => ':count gün',
- 'a_day' => '{1}bir gün|]1,Inf[:count gün',
- 'd' => ':countg',
- 'hour' => ':count saat',
- 'a_hour' => '{1}bir saat|]1,Inf[:count saat',
- 'h' => ':countsa',
- 'minute' => ':count dakika',
- 'a_minute' => '{1}bir dakika|]1,Inf[:count dakika',
- 'min' => ':countdk',
- 'second' => ':count saniye',
- 'a_second' => '{1}birkaç saniye|]1,Inf[:count saniye',
- 's' => ':countsn',
- 'ago' => ':time önce',
- 'from_now' => ':time sonra',
- 'after' => ':time sonra',
- 'before' => ':time önce',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[bugün saat] LT',
- 'nextDay' => '[yarın saat] LT',
- 'nextWeek' => '[gelecek] dddd [saat] LT',
- 'lastDay' => '[dün] LT',
- 'lastWeek' => '[geçen] dddd [saat] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'Do':
- case 'DD':
- return $number;
- default:
- if ($number === 0) { // special case for zero
- return "$number'ıncı";
- }
-
- static $suffixes = [
- 1 => '\'inci',
- 5 => '\'inci',
- 8 => '\'inci',
- 70 => '\'inci',
- 80 => '\'inci',
- 2 => '\'nci',
- 7 => '\'nci',
- 20 => '\'nci',
- 50 => '\'nci',
- 3 => '\'üncü',
- 4 => '\'üncü',
- 100 => '\'üncü',
- 6 => '\'ncı',
- 9 => '\'uncu',
- 10 => '\'uncu',
- 30 => '\'uncu',
- 60 => '\'ıncı',
- 90 => '\'ıncı',
- ];
-
- $lastDigit = $number % 10;
-
- return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
- }
- },
- 'meridiem' => ['ÖÖ', 'ÖS', 'öö', 'ös'],
- 'months' => ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
- 'months_short' => ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
- 'weekdays' => ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],
- 'weekdays_short' => ['Paz', 'Pts', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'],
- 'weekdays_min' => ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' ve '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/tr.php', [
- 'weekdays_short' => ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
- 'weekdays_min' => ['Pa', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'D.MM.YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'D MMMM YYYY dddd h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/tr.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ts_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Sunguti', 'Nyenyenyani', 'Nyenyankulu', 'Dzivamisoko', 'Mudyaxihi', 'Khotavuxika', 'Mawuwani', 'Mhawuri', 'Ndzhati', 'Nhlangula', 'Hukuri', 'N\'wendzamhala'],
- 'months_short' => ['Sun', 'Yan', 'Kul', 'Dzi', 'Mud', 'Kho', 'Maw', 'Mha', 'Ndz', 'Nhl', 'Huk', 'N\'w'],
- 'weekdays' => ['Sonto', 'Musumbhunuku', 'Ravumbirhi', 'Ravunharhu', 'Ravumune', 'Ravuntlhanu', 'Mugqivela'],
- 'weekdays_short' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
- 'weekdays_min' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => 'malembe ya :count',
- 'y' => 'malembe ya :count',
- 'a_year' => 'malembe ya :count',
-
- 'month' => 'tin’hweti ta :count',
- 'm' => 'tin’hweti ta :count',
- 'a_month' => 'tin’hweti ta :count',
-
- 'week' => 'mavhiki ya :count',
- 'w' => 'mavhiki ya :count',
- 'a_week' => 'mavhiki ya :count',
-
- 'day' => 'masiku :count',
- 'd' => 'masiku :count',
- 'a_day' => 'masiku :count',
-
- 'hour' => 'tiawara ta :count',
- 'h' => 'tiawara ta :count',
- 'a_hour' => 'tiawara ta :count',
-
- 'minute' => 'timinete ta :count',
- 'min' => 'timinete ta :count',
- 'a_minute' => 'timinete ta :count',
-
- 'second' => 'tisekoni ta :count',
- 's' => 'tisekoni ta :count',
- 'a_second' => 'tisekoni ta :count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/tt_RU.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Rinat Norkin Pablo Saratxaga, Rinat Norkin pablo@mandrakesoft.com, rinat@taif.ru
- */
-return [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'DD MMM, HH:mm',
- 'LLLL' => 'DD MMMM YYYY, HH:mm',
- ],
- 'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
- 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'weekdays' => ['якшәмбе', 'дышәмбе', 'сишәмбе', 'чәршәәмбе', 'пәнҗешмбе', 'җомга', 'шимбә'],
- 'weekdays_short' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'],
- 'weekdays_min' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'year' => ':count ел',
- 'month' => ':count ай',
- 'week' => ':count атна',
- 'day' => ':count көн',
- 'hour' => ':count сәгать',
- 'minute' => ':count минут',
- 'second' => ':count секунд',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Reshat Sabiq tatar.iqtelif.i18n@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD.MM.YYYY',
- ],
- 'months' => ['Ğınwar', 'Fiwral\'', 'Mart', 'April', 'May', 'Yün', 'Yül', 'Awgust', 'Sintebír', 'Üktebír', 'Noyebír', 'Dikebír'],
- 'months_short' => ['Ğın', 'Fiw', 'Mar', 'Apr', 'May', 'Yün', 'Yül', 'Awg', 'Sin', 'Ükt', 'Noy', 'Dik'],
- 'weekdays' => ['Yekşembí', 'Düşembí', 'Sişembí', 'Çerşembí', 'Pencíşembí', 'Comğa', 'Şimbe'],
- 'weekdays_short' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'],
- 'weekdays_min' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ÖA', 'ÖS'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/ses.php', [
- 'meridiem' => ['Subbaahi', 'Zaarikay b'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number > 1 ? 1 : 0;
-}, 'tzl');
-
-return [
- 'year' => ':count ar|:count ars',
- 'y' => ':count ar|:count ars',
- 'month' => ':count mes|:count mesen',
- 'm' => ':count mes|:count mesen',
- 'week' => ':count seifetziua|:count seifetziuas',
- 'w' => ':count seifetziua|:count seifetziuas',
- 'day' => ':count ziua|:count ziuas',
- 'd' => ':count ziua|:count ziuas',
- 'hour' => ':count þora|:count þoras',
- 'h' => ':count þora|:count þoras',
- 'minute' => ':count míut|:count míuts',
- 'min' => ':count míut|:count míuts',
- 'second' => ':count secunds',
- 's' => ':count secunds',
-
- 'ago' => 'ja :time',
- 'from_now' => 'osprei :time',
-
- 'diff_yesterday' => 'ieiri',
- 'diff_tomorrow' => 'demà',
-
- 'formats' => [
- 'LT' => 'HH.mm',
- 'LTS' => 'HH.mm.ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D. MMMM [dallas] YYYY',
- 'LLL' => 'D. MMMM [dallas] YYYY HH.mm',
- 'LLLL' => 'dddd, [li] D. MMMM [dallas] YYYY HH.mm',
- ],
-
- 'calendar' => [
- 'sameDay' => '[oxhi à] LT',
- 'nextDay' => '[demà à] LT',
- 'nextWeek' => 'dddd [à] LT',
- 'lastDay' => '[ieiri à] LT',
- 'lastWeek' => '[sür el] dddd [lasteu à] LT',
- 'sameElse' => 'L',
- ],
-
- 'meridiem' => ["D'A", "D'O"],
- 'months' => ['Januar', 'Fevraglh', 'Març', 'Avrïu', 'Mai', 'Gün', 'Julia', 'Guscht', 'Setemvar', 'Listopäts', 'Noemvar', 'Zecemvar'],
- 'months_short' => ['Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Gün', 'Jul', 'Gus', 'Set', 'Lis', 'Noe', 'Zec'],
- 'weekdays' => ['Súladi', 'Lúneçi', 'Maitzi', 'Márcuri', 'Xhúadi', 'Viénerçi', 'Sáturi'],
- 'weekdays_short' => ['Súl', 'Lún', 'Mai', 'Már', 'Xhú', 'Vié', 'Sát'],
- 'weekdays_min' => ['Sú', 'Lú', 'Ma', 'Má', 'Xh', 'Vi', 'Sá'],
- 'ordinal' => ':number.',
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'tzm');
-
-/*
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- */
-return [
- 'year' => 'ⴰⵙⴳⴰⵙ|:count ⵉⵙⴳⴰⵙⵏ',
- 'month' => 'ⴰⵢoⵓⵔ|:count ⵉⵢⵢⵉⵔⵏ',
- 'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ',
- 'day' => 'ⴰⵙⵙ|:count oⵙⵙⴰⵏ',
- 'hour' => 'ⵙⴰⵄⴰ|:count ⵜⴰⵙⵙⴰⵄⵉⵏ',
- 'minute' => 'ⵎⵉⵏⵓⴺ|:count ⵎⵉⵏⵓⴺ',
- 'second' => 'ⵉⵎⵉⴽ|:count ⵉⵎⵉⴽ',
- 'ago' => 'ⵢⴰⵏ :time',
- 'from_now' => 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ :time',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[ⴰⵙⴷⵅ ⴴ] LT',
- 'nextDay' => '[ⴰⵙⴽⴰ ⴴ] LT',
- 'nextWeek' => 'dddd [ⴴ] LT',
- 'lastDay' => '[ⴰⵚⴰⵏⵜ ⴴ] LT',
- 'lastWeek' => 'dddd [ⴴ] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'],
- 'months_short' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'],
- 'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
- 'weekdays_short' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
- 'weekdays_min' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
- 'weekend' => [5, 6],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'tzm');
-
-/*
- * Authors:
- * - Josh Soref
- * - JD Isaacks
- */
-return [
- 'year' => ':count asgas|:count isgasn',
- 'a_year' => 'asgas|:count isgasn',
- 'month' => ':count ayowr|:count iyyirn',
- 'a_month' => 'ayowr|:count iyyirn',
- 'week' => ':count imalass',
- 'a_week' => ':imalass',
- 'day' => ':count ass|:count ossan',
- 'a_day' => 'ass|:count ossan',
- 'hour' => ':count saɛa|:count tassaɛin',
- 'a_hour' => 'saɛa|:count tassaɛin',
- 'minute' => ':count minuḍ',
- 'a_minute' => 'minuḍ|:count minuḍ',
- 'second' => ':count imik',
- 'a_second' => 'imik|:count imik',
- 'ago' => 'yan :time',
- 'from_now' => 'dadkh s yan :time',
- 'diff_yesterday' => 'assant',
- 'diff_tomorrow' => 'aska',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[asdkh g] LT',
- 'nextDay' => '[aska g] LT',
- 'nextWeek' => 'dddd [g] LT',
- 'lastDay' => '[assant g] LT',
- 'lastWeek' => 'dddd [g] LT',
- 'sameElse' => 'L',
- ],
- 'months' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'],
- 'months_short' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'],
- 'weekdays' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
- 'weekdays_short' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
- 'weekdays_min' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
- 'meridiem' => ['Zdat azal', 'Ḍeffir aza'],
- 'first_day_of_week' => 6,
- 'day_of_first_week_of_year' => 1,
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'ug');
-
-/*
- * Authors:
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - yasinn
- */
-return [
- 'year' => 'بىر يىل|:count يىل',
- 'month' => 'بىر ئاي|:count ئاي',
- 'week' => 'بىر ھەپتە|:count ھەپتە',
- 'day' => 'بىر كۈن|:count كۈن',
- 'hour' => 'بىر سائەت|:count سائەت',
- 'minute' => 'بىر مىنۇت|:count مىنۇت',
- 'second' => 'نەچچە سېكونت|:count سېكونت',
- 'ago' => ':time بۇرۇن',
- 'from_now' => ':time كېيىن',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-DD',
- 'LL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى',
- 'LLL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
- 'LLLL' => 'dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[بۈگۈن سائەت] LT',
- 'nextDay' => '[ئەتە سائەت] LT',
- 'nextWeek' => '[كېلەركى] dddd [سائەت] LT',
- 'lastDay' => '[تۆنۈگۈن] LT',
- 'lastWeek' => '[ئالدىنقى] dddd [سائەت] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'-كۈنى';
- case 'w':
- case 'W':
- return $number.'-ھەپتە';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour, $minute) {
- $time = $hour * 100 + $minute;
- if ($time < 600) {
- return 'يېرىم كېچە';
- }
- if ($time < 900) {
- return 'سەھەر';
- }
- if ($time < 1130) {
- return 'چۈشتىن بۇرۇن';
- }
- if ($time < 1230) {
- return 'چۈش';
- }
- if ($time < 1800) {
- return 'چۈشتىن كېيىن';
- }
-
- return 'كەچ';
- },
- 'months' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
- 'months_short' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
- 'weekdays' => ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە', 'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'],
- 'weekdays_short' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],
- 'weekdays_min' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' ۋە '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Kunal Marwaha
- * - Alim Boyaq
- */
-return require __DIR__.'/ug.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-$processHoursFunction = function (\Carbon\CarbonInterface $date, string $format) {
- return $format.'о'.($date->hour === 11 ? 'б' : '').'] LT';
-};
-
-/*
- * Authors:
- * - Kunal Marwaha
- * - Josh Soref
- * - François B
- * - Tim Fish
- * - Serhan Apaydın
- * - Max Mykhailenko
- * - JD Isaacks
- * - Max Kovpak
- * - AucT
- * - Philippe Vaucher
- * - Ilya Shaplyko
- * - Vadym Ievsieiev
- * - Denys Kurets
- * - Igor Kasyanchuk
- * - Tsutomu Kuroda
- * - tjku
- * - Max Melentiev
- * - Oleh
- * - epaminond
- * - Juanito Fatas
- * - Vitalii Khustochka
- * - Akira Matsuda
- * - Christopher Dell
- * - Enrique Vidal
- * - Simone Carletti
- * - Aaron Patterson
- * - Andriy Tyurnikov
- * - Nicolás Hock Isaza
- * - Iwakura Taro
- * - Andrii Ponomarov
- * - alecrabbit
- * - vystepanenko
- * - AlexWalkerson
- * - Andre Havryliuk (Andrend)
- */
-return [
- 'year' => ':count рік|:count роки|:count років',
- 'y' => ':countр',
- 'a_year' => '{1}рік|:count рік|:count роки|:count років',
- 'month' => ':count місяць|:count місяці|:count місяців',
- 'm' => ':countм',
- 'a_month' => '{1}місяць|:count місяць|:count місяці|:count місяців',
- 'week' => ':count тиждень|:count тижні|:count тижнів',
- 'w' => ':countт',
- 'a_week' => '{1}тиждень|:count тиждень|:count тижні|:count тижнів',
- 'day' => ':count день|:count дні|:count днів',
- 'd' => ':countд',
- 'a_day' => '{1}день|:count день|:count дні|:count днів',
- 'hour' => ':count година|:count години|:count годин',
- 'h' => ':countг',
- 'a_hour' => '{1}годину|:count година|:count години|:count годин',
- 'minute' => ':count хвилина|:count хвилини|:count хвилин',
- 'min' => ':countхв',
- 'a_minute' => '{1}хвилина|:count хвилину|:count хвилини|:count хвилин',
- 'second' => ':count секунда|:count секунди|:count секунд',
- 's' => ':countсек',
- 'a_second' => '{1}кілька секунд|:count секунду|:count секунди|:count секунд',
- 'ago' => ':time тому',
- 'from_now' => 'за :time',
- 'after' => ':time після',
- 'before' => ':time до',
- 'diff_now' => 'щойно',
- 'diff_yesterday' => 'вчора',
- 'diff_tomorrow' => 'завтра',
- 'diff_before_yesterday' => 'позавчора',
- 'diff_after_tomorrow' => 'післязавтра',
- 'period_recurrences' => 'один раз|:count рази|:count разів',
- 'period_interval' => 'кожні :interval',
- 'period_start_date' => 'з :date',
- 'period_end_date' => 'до :date',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY, HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
- return $processHoursFunction($date, '[Сьогодні ');
- },
- 'nextDay' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
- return $processHoursFunction($date, '[Завтра ');
- },
- 'nextWeek' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
- return $processHoursFunction($date, '[У] dddd [');
- },
- 'lastDay' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
- return $processHoursFunction($date, '[Вчора ');
- },
- 'lastWeek' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
- switch ($date->dayOfWeek) {
- case 0:
- case 3:
- case 5:
- case 6:
- return $processHoursFunction($date, '[Минулої] dddd [');
- default:
- return $processHoursFunction($date, '[Минулого] dddd [');
- }
- },
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'M':
- case 'd':
- case 'DDD':
- case 'w':
- case 'W':
- return $number.'-й';
- case 'D':
- return $number.'-го';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour) {
- if ($hour < 4) {
- return 'ночі';
- }
- if ($hour < 12) {
- return 'ранку';
- }
- if ($hour < 17) {
- return 'дня';
- }
-
- return 'вечора';
- },
- 'months' => ['січня', 'лютого', 'березня', 'квітня', 'травня', 'червня', 'липня', 'серпня', 'вересня', 'жовтня', 'листопада', 'грудня'],
- 'months_standalone' => ['січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень'],
- 'months_short' => ['січ', 'лют', 'бер', 'кві', 'тра', 'чер', 'лип', 'сер', 'вер', 'жов', 'лис', 'гру'],
- 'months_regexp' => '/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/',
- 'weekdays' => function (\Carbon\CarbonInterface $date, $format, $index) {
- static $words = [
- 'nominative' => ['неділя', 'понеділок', 'вівторок', 'середа', 'четвер', 'п’ятниця', 'субота'],
- 'accusative' => ['неділю', 'понеділок', 'вівторок', 'середу', 'четвер', 'п’ятницю', 'суботу'],
- 'genitive' => ['неділі', 'понеділка', 'вівторка', 'середи', 'четверга', 'п’ятниці', 'суботи'],
- ];
-
- $nounCase = preg_match('/(\[(В|в|У|у)\])\s+dddd/', $format) ?
- 'accusative' :
- (preg_match('/\[?(?:минулої|наступної)?\s*\]\s+dddd/', $format) ?
- 'genitive' :
- 'nominative'
- );
-
- return $words[$nounCase][$index] ?? null;
- },
- 'weekdays_short' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
- 'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' i '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/uk.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/unm_US.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['enikwsi', 'chkwali', 'xamokhwite', 'kwetayoxe', 'tainipen', 'kichinipen', 'lainipen', 'winaminke', 'kichitahkok', 'puksit', 'wini', 'muxkotae'],
- 'months_short' => ['eni', 'chk', 'xam', 'kwe', 'tai', 'nip', 'lai', 'win', 'tah', 'puk', 'kun', 'mux'],
- 'weekdays' => ['kentuwei', 'manteke', 'tusteke', 'lelai', 'tasteke', 'pelaiteke', 'sateteke'],
- 'weekdays_short' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'],
- 'weekdays_min' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'],
- 'day_of_first_week_of_year' => 1,
-
- // Too unreliable
- /*
- 'year' => ':count kaxtëne',
- 'y' => ':count kaxtëne',
- 'a_year' => ':count kaxtëne',
-
- 'month' => ':count piskewëni kishux', // less reliable
- 'm' => ':count piskewëni kishux', // less reliable
- 'a_month' => ':count piskewëni kishux', // less reliable
-
- 'week' => ':count kishku', // less reliable
- 'w' => ':count kishku', // less reliable
- 'a_week' => ':count kishku', // less reliable
-
- 'day' => ':count kishku',
- 'd' => ':count kishku',
- 'a_day' => ':count kishku',
-
- 'hour' => ':count xkuk', // less reliable
- 'h' => ':count xkuk', // less reliable
- 'a_hour' => ':count xkuk', // less reliable
-
- 'minute' => ':count txituwàk', // less reliable
- 'min' => ':count txituwàk', // less reliable
- 'a_minute' => ':count txituwàk', // less reliable
-
- 'second' => ':count nisha', // less reliable
- 's' => ':count nisha', // less reliable
- 'a_second' => ':count nisha', // less reliable
- */
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-$months = [
- 'جنوری',
- 'فروری',
- 'مارچ',
- 'اپریل',
- 'مئی',
- 'جون',
- 'جولائی',
- 'اگست',
- 'ستمبر',
- 'اکتوبر',
- 'نومبر',
- 'دسمبر',
-];
-
-$weekdays = [
- 'اتوار',
- 'پیر',
- 'منگل',
- 'بدھ',
- 'جمعرات',
- 'جمعہ',
- 'ہفتہ',
-];
-
-/*
- * Authors:
- * - Sawood Alam
- * - Mehshan
- * - Philippe Vaucher
- * - Tsutomu Kuroda
- * - tjku
- * - Zaid Akram
- * - Max Melentiev
- * - hafezdivandari
- * - Hossein Jabbari
- * - nimamo
- */
-return [
- 'year' => 'ایک سال|:count سال',
- 'month' => 'ایک ماہ|:count ماہ',
- 'week' => ':count ہفتے',
- 'day' => 'ایک دن|:count دن',
- 'hour' => 'ایک گھنٹہ|:count گھنٹے',
- 'minute' => 'ایک منٹ|:count منٹ',
- 'second' => 'چند سیکنڈ|:count سیکنڈ',
- 'ago' => ':time قبل',
- 'from_now' => ':time بعد',
- 'after' => ':time بعد',
- 'before' => ':time پہلے',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd، D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[آج بوقت] LT',
- 'nextDay' => '[کل بوقت] LT',
- 'nextWeek' => 'dddd [بوقت] LT',
- 'lastDay' => '[گذشتہ روز بوقت] LT',
- 'lastWeek' => '[گذشتہ] dddd [بوقت] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['صبح', 'شام'],
- 'months' => $months,
- 'months_short' => $months,
- 'weekdays' => $weekdays,
- 'weekdays_short' => $weekdays,
- 'weekdays_min' => $weekdays,
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => ['، ', ' اور '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Red Hat, Pune bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ur.php', [
- 'formats' => [
- 'L' => 'D/M/YY',
- ],
- 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'weekdays' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
- 'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
- 'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/ur.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
- 'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
- 'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ص', 'ش'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'uz');
-
-/*
- * Authors:
- * - Dmitriy Shabanov
- * - JD Isaacks
- * - Inoyatulloh
- * - Jamshid
- * - aarkhipov
- * - Philippe Vaucher
- * - felixthemagnificent
- * - Tsutomu Kuroda
- * - tjku
- * - Max Melentiev
- * - Juanito Fatas
- * - Alisher Ulugbekov
- */
-return [
- 'year' => ':count йил',
- 'a_year' => 'бир йил|:count йил',
- 'y' => ':count й',
- 'month' => ':count ой',
- 'a_month' => 'бир ой|:count ой',
- 'm' => ':count о',
- 'week' => ':count ҳафта',
- 'a_week' => 'бир ҳафта|:count ҳафта',
- 'w' => ':count ҳ',
- 'day' => ':count кун',
- 'a_day' => 'бир кун|:count кун',
- 'd' => ':count к',
- 'hour' => ':count соат',
- 'a_hour' => 'бир соат|:count соат',
- 'h' => ':count с',
- 'minute' => ':count дакика',
- 'a_minute' => 'бир дакика|:count дакика',
- 'min' => ':count д',
- 'second' => ':count фурсат',
- 'a_second' => 'фурсат|:count фурсат',
- 's' => ':count ф',
- 'ago' => 'Бир неча :time олдин',
- 'from_now' => 'Якин :time ичида',
- 'after' => ':time пас аз он',
- 'before' => ':time пеш аз он',
- 'diff_yesterday' => 'Кеча',
- 'diff_tomorrow' => 'Эртага',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'D MMMM YYYY, dddd HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Бугун соат] LT [да]',
- 'nextDay' => '[Эртага] LT [да]',
- 'nextWeek' => 'dddd [куни соат] LT [да]',
- 'lastDay' => '[Кеча соат] LT [да]',
- 'lastWeek' => '[Утган] dddd [куни соат] LT [да]',
- 'sameElse' => 'L',
- ],
- 'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'],
- 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
- 'weekdays' => ['якшанба', 'душанба', 'сешанба', 'чоршанба', 'пайшанба', 'жума', 'шанба'],
- 'weekdays_short' => ['якш', 'душ', 'сеш', 'чор', 'пай', 'жум', 'шан'],
- 'weekdays_min' => ['як', 'ду', 'се', 'чо', 'па', 'жу', 'ша'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ertalab', 'kechasi'],
- 'list' => [', ', ' va '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/fa.php', [
- 'weekdays' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
- 'weekdays_short' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
- 'weekdays_min' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
- 'months' => ['جنوری', 'فبروری', 'مارچ', 'اپریل', 'می', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
- 'months_short' => ['جنو', 'فبر', 'مار', 'اپر', 'می', 'جون', 'جول', 'اگس', 'سپت', 'اکت', 'نوم', 'دسم'],
- 'first_day_of_week' => 6,
- 'weekend' => [4, 5],
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/uz.php', [
- 'formats' => [
- 'L' => 'DD/MM/yy',
- 'LL' => 'D MMM, YYYY',
- 'LLL' => 'D MMMM, YYYY HH:mm',
- 'LLLL' => 'dddd, DD MMMM, YYYY HH:mm',
- ],
- 'meridiem' => ['ТО', 'ТК'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'uz');
-
-/*
- * Authors:
- * - Josh Soref
- * - Rasulbek
- */
-return [
- 'year' => ':count yil',
- 'a_year' => 'bir yil|:count yil',
- 'y' => ':count y',
- 'month' => ':count oy',
- 'a_month' => 'bir oy|:count oy',
- 'm' => ':count o',
- 'week' => ':count hafta',
- 'a_week' => 'bir hafta|:count hafta',
- 'w' => ':count h',
- 'day' => ':count kun',
- 'a_day' => 'bir kun|:count kun',
- 'd' => ':count k',
- 'hour' => ':count soat',
- 'a_hour' => 'bir soat|:count soat',
- 'h' => ':count soat',
- 'minute' => ':count daqiqa',
- 'a_minute' => 'bir daqiqa|:count daqiqa',
- 'min' => ':count d',
- 'second' => ':count soniya',
- 'a_second' => 'soniya|:count soniya',
- 's' => ':count son.',
- 'ago' => 'Bir necha :time oldin',
- 'from_now' => 'Yaqin :time ichida',
- 'diff_yesterday' => 'Kecha',
- 'diff_tomorrow' => 'Ertaga',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'D MMMM YYYY, dddd HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Bugun soat] LT [da]',
- 'nextDay' => '[Ertaga] LT [da]',
- 'nextWeek' => 'dddd [kuni soat] LT [da]',
- 'lastDay' => '[Kecha soat] LT [da]',
- 'lastWeek' => '[O\'tgan] dddd [kuni soat] LT [da]',
- 'sameElse' => 'L',
- ],
- 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
- 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
- 'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'],
- 'weekdays_short' => ['Yak', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum', 'Shan'],
- 'weekdays_min' => ['Ya', 'Du', 'Se', 'Cho', 'Pa', 'Ju', 'Sha'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' va '],
- 'meridiem' => ['TO', 'TK'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Bobir Ismailov Bobir Ismailov, Pablo Saratxaga, Mashrab Kuvatov bobir_is@yahoo.com, pablo@mandrakesoft.com, kmashrab@uni-bremen.de
- */
-return array_replace_recursive(require __DIR__.'/uz_Latn.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
- 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyn', 'Iyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
- 'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'],
- 'weekdays_short' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'],
- 'weekdays_min' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Mashrab Kuvatov Mashrab Kuvatov, Pablo Saratxaga kmashrab@uni-bremen.de, pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/uz.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['Январ', 'Феврал', 'Март', 'Апрел', 'Май', 'Июн', 'Июл', 'Август', 'Сентябр', 'Октябр', 'Ноябр', 'Декабр'],
- 'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
- 'weekdays' => ['Якшанба', 'Душанба', 'Сешанба', 'Чоршанба', 'Пайшанба', 'Жума', 'Шанба'],
- 'weekdays_short' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'],
- 'weekdays_min' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
- 'weekdays_short' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
- 'weekdays_min' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
- 'months' => ['ꖨꖕ ꕪꕴ ꔞꔀꕮꕊ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞꔤ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ', 'ꖨꖕ ꕪꕴ ꗏꖺꕮꕊ'],
- 'months_short' => ['ꖨꖕꔞ', 'ꕒꕡ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋ', 'ꖨꖕꗏ'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
- ],
-
- 'year' => ':count ꕀ', // less reliable
- 'y' => ':count ꕀ', // less reliable
- 'a_year' => ':count ꕀ', // less reliable
-
- 'second' => ':count ꗱꕞꕯꕊ', // less reliable
- 's' => ':count ꗱꕞꕯꕊ', // less reliable
- 'a_second' => ':count ꗱꕞꕯꕊ', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'weekdays' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
- 'weekdays_short' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
- 'weekdays_min' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
- 'months' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
- 'months_short' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'h:mm a',
- 'LTS' => 'h:mm:ss a',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm a',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/vai.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/ve_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Phando', 'Luhuhi', 'Ṱhafamuhwe', 'Lambamai', 'Shundunthule', 'Fulwi', 'Fulwana', 'Ṱhangule', 'Khubvumedzi', 'Tshimedzi', 'Ḽara', 'Nyendavhusiku'],
- 'months_short' => ['Pha', 'Luh', 'Fam', 'Lam', 'Shu', 'Lwi', 'Lwa', 'Ngu', 'Khu', 'Tsh', 'Ḽar', 'Nye'],
- 'weekdays' => ['Swondaha', 'Musumbuluwo', 'Ḽavhuvhili', 'Ḽavhuraru', 'Ḽavhuṋa', 'Ḽavhuṱanu', 'Mugivhela'],
- 'weekdays_short' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'],
- 'weekdays_min' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'],
- 'day_of_first_week_of_year' => 1,
-
- // Too unreliable
- /*
- 'day' => ':count vhege', // less reliable
- 'd' => ':count vhege', // less reliable
- 'a_day' => ':count vhege', // less reliable
-
- 'hour' => ':count watshi', // less reliable
- 'h' => ':count watshi', // less reliable
- 'a_hour' => ':count watshi', // less reliable
-
- 'minute' => ':count watshi', // less reliable
- 'min' => ':count watshi', // less reliable
- 'a_minute' => ':count watshi', // less reliable
-
- 'second' => ':count Mu', // less reliable
- 's' => ':count Mu', // less reliable
- 'a_second' => ':count Mu', // less reliable
-
- 'week' => ':count vhege',
- 'w' => ':count vhege',
- 'a_week' => ':count vhege',
- */
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - François B
- * - Andre Polykanine A.K.A. Menelion Elensúlë
- * - JD Isaacks
- */
-return [
- 'year' => ':count năm',
- 'a_year' => '{1}một năm|]1, Inf[:count năm',
- 'y' => ':count năm',
- 'month' => ':count tháng',
- 'a_month' => '{1}một tháng|]1, Inf[:count tháng',
- 'm' => ':count tháng',
- 'week' => ':count tuần',
- 'a_week' => '{1}một tuần|]1, Inf[:count tuần',
- 'w' => ':count tuần',
- 'day' => ':count ngày',
- 'a_day' => '{1}một ngày|]1, Inf[:count ngày',
- 'd' => ':count ngày',
- 'hour' => ':count giờ',
- 'a_hour' => '{1}một giờ|]1, Inf[:count giờ',
- 'h' => ':count giờ',
- 'minute' => ':count phút',
- 'a_minute' => '{1}một phút|]1, Inf[:count phút',
- 'min' => ':count phút',
- 'second' => ':count giây',
- 'a_second' => '{1}vài giây|]1, Inf[:count giây',
- 's' => ':count giây',
- 'ago' => ':time trước',
- 'from_now' => ':time tới',
- 'after' => ':time sau',
- 'before' => ':time trước',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM [năm] YYYY',
- 'LLL' => 'D MMMM [năm] YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM [năm] YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[Hôm nay lúc] LT',
- 'nextDay' => '[Ngày mai lúc] LT',
- 'nextWeek' => 'dddd [tuần tới lúc] LT',
- 'lastDay' => '[Hôm qua lúc] LT',
- 'lastWeek' => 'dddd [tuần trước lúc] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['SA', 'CH'],
- 'months' => ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5', 'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11', 'tháng 12'],
- 'months_short' => ['Th01', 'Th02', 'Th03', 'Th04', 'Th05', 'Th06', 'Th07', 'Th08', 'Th09', 'Th10', 'Th11', 'Th12'],
- 'weekdays' => ['chủ nhật', 'thứ hai', 'thứ ba', 'thứ tư', 'thứ năm', 'thứ sáu', 'thứ bảy'],
- 'weekdays_short' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
- 'weekdays_min' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => [', ', ' và '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/vi.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
- 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY-MM-dd',
- 'LL' => 'YYYY MMM D',
- 'LLL' => 'YYYY MMMM D HH:mm',
- 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
- ],
-
- 'year' => ':count yel',
- 'y' => ':count yel',
- 'a_year' => ':count yel',
-
- 'month' => ':count mul',
- 'm' => ':count mul',
- 'a_month' => ':count mul',
-
- 'week' => ':count vig',
- 'w' => ':count vig',
- 'a_week' => ':count vig',
-
- 'day' => ':count del',
- 'd' => ':count del',
- 'a_day' => ':count del',
-
- 'hour' => ':count düp',
- 'h' => ':count düp',
- 'a_hour' => ':count düp',
-
- 'minute' => ':count minut',
- 'min' => ':count minut',
- 'a_minute' => ':count minut',
-
- 'second' => ':count sekun',
- 's' => ':count sekun',
- 'a_second' => ':count sekun',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['utuko', 'kyiukonyi'],
- 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
- 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
- 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/wa_BE.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Djan SACRE Pablo Saratxaga pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['di djanvî', 'di fevrî', 'di måss', 'd’ avri', 'di may', 'di djun', 'di djulete', 'd’ awousse', 'di setimbe', 'd’ octôbe', 'di nôvimbe', 'di decimbe'],
- 'months_short' => ['dja', 'fev', 'mås', 'avr', 'may', 'djn', 'djl', 'awo', 'set', 'oct', 'nôv', 'dec'],
- 'weekdays' => ['dimegne', 'londi', 'mårdi', 'mierkidi', 'djudi', 'vénrdi', 'semdi'],
- 'weekdays_short' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'],
- 'weekdays_min' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'year' => ':count anêye',
- 'y' => ':count anêye',
- 'a_year' => ':count anêye',
-
- 'month' => ':count meûs',
- 'm' => ':count meûs',
- 'a_month' => ':count meûs',
-
- 'week' => ':count samwinne',
- 'w' => ':count samwinne',
- 'a_week' => ':count samwinne',
-
- 'day' => ':count djoû',
- 'd' => ':count djoû',
- 'a_day' => ':count djoû',
-
- 'hour' => ':count eure',
- 'h' => ':count eure',
- 'a_hour' => ':count eure',
-
- 'minute' => ':count munute',
- 'min' => ':count munute',
- 'a_minute' => ':count munute',
-
- 'second' => ':count Sigonde',
- 's' => ':count Sigonde',
- 'a_second' => ':count Sigonde',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/wae_CH.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Walser Translation Team ml@translate-wae.ch
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
- 'months' => ['Jenner', 'Hornig', 'Märze', 'Abrille', 'Meije', 'Bráčet', 'Heiwet', 'Öigšte', 'Herbštmánet', 'Wímánet', 'Wintermánet', 'Chrištmánet'],
- 'months_short' => ['Jen', 'Hor', 'Mär', 'Abr', 'Mei', 'Brá', 'Hei', 'Öig', 'Her', 'Wím', 'Win', 'Chr'],
- 'weekdays' => ['Suntag', 'Mäntag', 'Zischtag', 'Mittwuch', 'Frontag', 'Fritag', 'Samschtag'],
- 'weekdays_short' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'],
- 'weekdays_min' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
-
- 'month' => ':count Maano', // less reliable
- 'm' => ':count Maano', // less reliable
- 'a_month' => ':count Maano', // less reliable
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/wal_ET.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Ge'ez Frontier Foundation locales@geez.org
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
- 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
- 'weekdays' => ['ወጋ', 'ሳይኖ', 'ማቆሳኛ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ'],
- 'weekdays_short' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '],
- 'weekdays_min' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '],
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['ማለዶ', 'ቃማ'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/wo_SN.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - The Debian Project Christian Perrier bubulle@debian.org
- */
-return [
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD.MM.YYYY',
- 'LL' => 'MMMM DD, YYYY',
- 'LLL' => 'DD MMM HH:mm',
- 'LLLL' => 'MMMM DD, YYYY HH:mm',
- ],
- 'months' => ['sanwiy\'e', 'feebriy\'e', 'mars', 'awril', 'me', 'suwen', 'sulet', 'uut', 'septaambar', 'oktoobar', 'nowaambar', 'desaambar'],
- 'months_short' => ['san', 'fee', 'mar', 'awr', 'me ', 'suw', 'sul', 'uut', 'sep', 'okt', 'now', 'des'],
- 'weekdays' => ['dib\'eer', 'altine', 'talaata', 'allarba', 'alxames', 'ajjuma', 'gaawu'],
- 'weekdays_short' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'],
- 'weekdays_min' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'year' => ':count at',
- 'month' => ':count wèr',
- 'week' => ':count ayubés',
- 'day' => ':count bés',
- 'hour' => ':count waxtu',
- 'minute' => ':count simili',
- 'second' => ':count saa',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/xh_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['eyoMqungu', 'eyoMdumba', 'eyoKwindla', 'uTshazimpuzi', 'uCanzibe', 'eyeSilimela', 'eyeKhala', 'eyeThupa', 'eyoMsintsi', 'eyeDwarha', 'eyeNkanga', 'eyoMnga'],
- 'months_short' => ['Mqu', 'Mdu', 'Kwi', 'Tsh', 'Can', 'Sil', 'Kha', 'Thu', 'Msi', 'Dwa', 'Nka', 'Mng'],
- 'weekdays' => ['iCawa', 'uMvulo', 'lwesiBini', 'lwesiThathu', 'ulweSine', 'lwesiHlanu', 'uMgqibelo'],
- 'weekdays_short' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'],
- 'weekdays_min' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count ihlobo', // less reliable
- 'y' => ':count ihlobo', // less reliable
- 'a_year' => ':count ihlobo', // less reliable
-
- 'hour' => ':count iwotshi', // less reliable
- 'h' => ':count iwotshi', // less reliable
- 'a_hour' => ':count iwotshi', // less reliable
-
- 'minute' => ':count ingqalelo', // less reliable
- 'min' => ':count ingqalelo', // less reliable
- 'a_minute' => ':count ingqalelo', // less reliable
-
- 'second' => ':count nceda', // less reliable
- 's' => ':count nceda', // less reliable
- 'a_second' => ':count nceda', // less reliable
-
- 'month' => ':count inyanga',
- 'm' => ':count inyanga',
- 'a_month' => ':count inyanga',
-
- 'week' => ':count veki',
- 'w' => ':count veki',
- 'a_week' => ':count veki',
-
- 'day' => ':count imini',
- 'd' => ':count imini',
- 'a_day' => ':count imini',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['Munkyo', 'Eigulo'],
- 'weekdays' => ['Sabiiti', 'Balaza', 'Owokubili', 'Owokusatu', 'Olokuna', 'Olokutaanu', 'Olomukaaga'],
- 'weekdays_short' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
- 'weekdays_min' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
- 'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
- 'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'meridiem' => ['kiɛmɛ́ɛm', 'kisɛ́ndɛ'],
- 'weekdays' => ['sɔ́ndiɛ', 'móndie', 'muányáŋmóndie', 'metúkpíápɛ', 'kúpélimetúkpiapɛ', 'feléte', 'séselé'],
- 'weekdays_short' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
- 'weekdays_min' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
- 'months' => ['pikítíkítie, oólí ú kutúan', 'siɛyɛ́, oóli ú kándíɛ', 'ɔnsúmbɔl, oóli ú kátátúɛ', 'mesiŋ, oóli ú kénie', 'ensil, oóli ú kátánuɛ', 'ɔsɔn', 'efute', 'pisuyú', 'imɛŋ i puɔs', 'imɛŋ i putúk,oóli ú kátíɛ', 'makandikɛ', 'pilɔndɔ́'],
- 'months_short' => ['o.1', 'o.2', 'o.3', 'o.4', 'o.5', 'o.6', 'o.7', 'o.8', 'o.9', 'o.10', 'o.11', 'o.12'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'D/M/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/yi_US.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - http://www.uyip.org/ Pablo Saratxaga pablo@mandrakesoft.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['יאַנואַר', 'פֿעברואַר', 'מערץ', 'אַפּריל', 'מיי', 'יוני', 'יולי', 'אויגוסט', 'סעפּטעמבער', 'אקטאבער', 'נאוועמבער', 'דעצעמבער'],
- 'months_short' => ['יאַנ', 'פֿעב', 'מאַר', 'אַפּר', 'מײַ ', 'יונ', 'יול', 'אױג', 'סעפּ', 'אָקט', 'נאָװ', 'דעצ'],
- 'weekdays' => ['זונטיק', 'מאָנטיק', 'דינסטיק', 'מיטװאָך', 'דאָנערשטיק', 'פֿרײַטיק', 'שבת'],
- 'weekdays_short' => ['זונ\'', 'מאָנ\'', 'דינ\'', 'מיט\'', 'דאָנ\'', 'פֿרײַ\'', 'שבת'],
- 'weekdays_min' => ['זונ\'', 'מאָנ\'', 'דינ\'', 'מיט\'', 'דאָנ\'', 'פֿרײַ\'', 'שבת'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => ':count יאר',
- 'y' => ':count יאר',
- 'a_year' => ':count יאר',
-
- 'month' => ':count חודש',
- 'm' => ':count חודש',
- 'a_month' => ':count חודש',
-
- 'week' => ':count וואָך',
- 'w' => ':count וואָך',
- 'a_week' => ':count וואָך',
-
- 'day' => ':count טאָג',
- 'd' => ':count טאָג',
- 'a_day' => ':count טאָג',
-
- 'hour' => ':count שעה',
- 'h' => ':count שעה',
- 'a_hour' => ':count שעה',
-
- 'minute' => ':count מינוט',
- 'min' => ':count מינוט',
- 'a_minute' => ':count מינוט',
-
- 'second' => ':count סעקונדע',
- 's' => ':count סעקונדע',
- 'a_second' => ':count סעקונדע',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
- return $number === 1 ? 0 : 1;
-}, 'yo');
-
-/*
- * Authors:
- * - François B
- * - Atolagbe Abisoye
- */
-return [
- 'year' => 'ọdún :count',
- 'a_year' => 'ọdún kan|ọdún :count',
- 'month' => 'osù :count',
- 'a_month' => 'osù kan|osù :count',
- 'week' => 'ọsẹ :count',
- 'a_week' => 'ọsẹ kan|ọsẹ :count',
- 'day' => 'ọjọ́ :count',
- 'a_day' => 'ọjọ́ kan|ọjọ́ :count',
- 'hour' => 'wákati :count',
- 'a_hour' => 'wákati kan|wákati :count',
- 'minute' => 'ìsẹjú :count',
- 'a_minute' => 'ìsẹjú kan|ìsẹjú :count',
- 'second' => 'iaayá :count',
- 'a_second' => 'ìsẹjú aayá die|aayá :count',
- 'ago' => ':time kọjá',
- 'from_now' => 'ní :time',
- 'diff_yesterday' => 'Àna',
- 'diff_tomorrow' => 'Ọ̀la',
- 'formats' => [
- 'LT' => 'h:mm A',
- 'LTS' => 'h:mm:ss A',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY h:mm A',
- 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
- ],
- 'calendar' => [
- 'sameDay' => '[Ònì ni] LT',
- 'nextDay' => '[Ọ̀la ni] LT',
- 'nextWeek' => 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT',
- 'lastDay' => '[Àna ni] LT',
- 'lastWeek' => 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => 'ọjọ́ :number',
- 'months' => ['Sẹ́rẹ́', 'Èrèlè', 'Ẹrẹ̀nà', 'Ìgbé', 'Èbibi', 'Òkùdu', 'Agẹmo', 'Ògún', 'Owewe', 'Ọ̀wàrà', 'Bélú', 'Ọ̀pẹ̀̀'],
- 'months_short' => ['Sẹ́r', 'Èrl', 'Ẹrn', 'Ìgb', 'Èbi', 'Òkù', 'Agẹ', 'Ògú', 'Owe', 'Ọ̀wà', 'Bél', 'Ọ̀pẹ̀̀'],
- 'weekdays' => ['Àìkú', 'Ajé', 'Ìsẹ́gun', 'Ọjọ́rú', 'Ọjọ́bọ', 'Ẹtì', 'Àbámẹ́ta'],
- 'weekdays_short' => ['Àìk', 'Ajé', 'Ìsẹ́', 'Ọjr', 'Ọjb', 'Ẹtì', 'Àbá'],
- 'weekdays_min' => ['Àì', 'Aj', 'Ìs', 'Ọr', 'Ọb', 'Ẹt', 'Àb'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'meridiem' => ['Àárọ̀', 'Ọ̀sán'],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/yo.php', [
- 'meridiem' => ['Àárɔ̀', 'Ɔ̀sán'],
- 'weekdays' => ['Ɔjɔ́ Àìkú', 'Ɔjɔ́ Ajé', 'Ɔjɔ́ Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɔjɔ́ Ɛtì', 'Ɔjɔ́ Àbámɛ́ta'],
- 'weekdays_short' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
- 'weekdays_min' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
- 'months' => ['Oshù Shɛ́rɛ́', 'Oshù Èrèlè', 'Oshù Ɛrɛ̀nà', 'Oshù Ìgbé', 'Oshù Ɛ̀bibi', 'Oshù Òkúdu', 'Oshù Agɛmɔ', 'Oshù Ògún', 'Oshù Owewe', 'Oshù Ɔ̀wàrà', 'Oshù Bélú', 'Oshù Ɔ̀pɛ̀'],
- 'months_short' => ['Shɛ́rɛ́', 'Èrèlè', 'Ɛrɛ̀nà', 'Ìgbé', 'Ɛ̀bibi', 'Òkúdu', 'Agɛmɔ', 'Ògún', 'Owewe', 'Ɔ̀wàrà', 'Bélú', 'Ɔ̀pɛ̀'],
- 'first_day_of_week' => 1,
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/yo.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/yue_HK.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/zh_HK.php', [
- 'formats' => [
- 'L' => 'YYYY年MM月DD日 dddd',
- ],
- 'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'first_day_of_week' => 0,
- 'day_of_first_week_of_year' => 1,
- 'meridiem' => ['上午', '下午'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hans.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hant.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/yuw_PG.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Information from native speakers Hannah Sarvasy nungon.localization@gmail.com
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YY',
- ],
- 'months' => ['jenuari', 'febuari', 'mas', 'epril', 'mei', 'jun', 'julai', 'ögus', 'septemba', 'öktoba', 'nöwemba', 'diksemba'],
- 'months_short' => ['jen', 'feb', 'mas', 'epr', 'mei', 'jun', 'jul', 'ögu', 'sep', 'ökt', 'nöw', 'dis'],
- 'weekdays' => ['sönda', 'mönda', 'sinda', 'mitiwö', 'sogipbono', 'nenggo', 'söndanggie'],
- 'weekdays_short' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'],
- 'weekdays_min' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - BAKTETE Miloud
- */
-return [
- 'year' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
- 'a_year' => 'ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
- 'y' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
- 'month' => ':count ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ',
- 'a_month' => 'ⵉⴷⵊ ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ',
- 'm' => ':count ⴰⵢⵢⵓⵔⵏ',
- 'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ',
- 'a_week' => 'ⵉⵛⵜ ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ',
- 'w' => ':count ⵉⵎⴰⵍⴰⵙⵙ.',
- 'day' => ':count ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ',
- 'a_day' => 'ⵉⴷⵊ ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ',
- 'd' => ':count ⵓ',
- 'hour' => ':count ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ',
- 'a_hour' => 'ⵉⵛⵜ ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ',
- 'h' => ':count ⵜ',
- 'minute' => ':count ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ',
- 'a_minute' => 'ⵉⵛⵜ ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ',
- 'min' => ':count ⵜⵓⵙ',
- 'second' => ':count ⵜⵙⵉⵏⵜ|:count ⵜⵉⵙⵉⵏⴰ',
- 'a_second' => 'ⴽⵔⴰ ⵜⵉⵙⵉⵏⴰ|:count ⵜⵉⵙⵉⵏⴰ',
- 's' => ':count ⵜ',
- 'ago' => 'ⵣⴳ :time',
- 'from_now' => 'ⴷⴳ :time',
- 'after' => ':time ⴰⵡⴰⵔ',
- 'before' => ':time ⴷⴰⵜ',
- 'diff_now' => 'ⴰⴷⵡⴰⵍⵉ',
- 'diff_yesterday' => 'ⴰⵙⵙⵏⵏⴰⵟ',
- 'diff_tomorrow' => 'ⴰⵙⴽⴽⴰ',
- 'diff_before_yesterday' => 'ⴼⵔ ⵉⴹⵏⵏⴰⵟ',
- 'diff_after_tomorrow' => 'ⵏⴰⴼ ⵓⵙⴽⴽⴰ',
- 'period_recurrences' => ':count ⵜⵉⴽⴽⴰⵍ',
- 'period_interval' => 'ⴽⵓ :interval',
- 'period_start_date' => 'ⴳ :date',
- 'period_end_date' => 'ⵉ :date',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'DD/MM/YYYY',
- 'LL' => 'D MMMM YYYY',
- 'LLL' => 'D MMMM YYYY HH:mm',
- 'LLLL' => 'dddd D MMMM YYYY HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[ⴰⵙⵙ ⴰ/ⴰⴷ ⴳ] LT',
- 'nextDay' => '[ⴰⵙⴽⴽⴰ ⴳ] LT',
- 'nextWeek' => 'dddd [ⴳ] LT',
- 'lastDay' => '[ⴰⵙⵙⵏⵏⴰⵟ ⴳ] LT',
- 'lastWeek' => 'dddd [ⴰⵎⴳⴳⴰⵔⵓ ⴳ] LT',
- 'sameElse' => 'L',
- ],
- 'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
- 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
- 'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵟⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
- 'weekdays' => ['ⵓⵙⴰⵎⴰⵙ', 'ⵡⴰⵢⵏⴰⵙ', 'ⵓⵙⵉⵏⴰⵙ', 'ⵡⴰⴽⵕⴰⵙ', 'ⵓⴽⵡⴰⵙ', 'ⵓⵙⵉⵎⵡⴰⵙ', 'ⵓⵙⵉⴹⵢⴰⵙ'],
- 'weekdays_short' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'],
- 'weekdays_min' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 1,
- 'list' => [', ', ' ⴷ '],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - xuri
- * - sycuato
- * - bokideckonja
- * - Luo Ning
- */
-return [
- 'year' => ':count年',
- 'y' => ':count年',
- 'month' => ':count个月',
- 'm' => ':count个月',
- 'week' => ':count周',
- 'w' => ':count周',
- 'day' => ':count天',
- 'd' => ':count天',
- 'hour' => ':count小时',
- 'h' => ':count小时',
- 'minute' => ':count分钟',
- 'min' => ':count分钟',
- 'second' => ':count秒',
- 's' => ':count秒',
- 'ago' => ':time前',
- 'from_now' => '距现在:time',
- 'after' => ':time后',
- 'before' => ':time前',
- 'diff_yesterday' => '昨天',
- 'diff_tomorrow' => '明天',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY年M月D日',
- 'LLL' => 'YYYY年M月D日 A h点mm分',
- 'LLLL' => 'YYYY年M月D日dddd A h点mm分',
- ],
- 'calendar' => [
- 'sameDay' => '[今天]LT',
- 'nextDay' => '[明天]LT',
- 'nextWeek' => '[下]ddddLT',
- 'lastDay' => '[昨天]LT',
- 'lastWeek' => '[上]ddddLT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'日';
- case 'M':
- return $number.'月';
- case 'w':
- case 'W':
- return $number.'周';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour, $minute) {
- $time = $hour * 100 + $minute;
- if ($time < 600) {
- return '凌晨';
- }
- if ($time < 900) {
- return '早上';
- }
- if ($time < 1130) {
- return '上午';
- }
- if ($time < 1230) {
- return '中午';
- }
- if ($time < 1800) {
- return '下午';
- }
-
- return '晚上';
- },
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => '',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - monkeycon
- * - François B
- * - Jason Katz-Brown
- * - Serhan Apaydın
- * - Matt Johnson
- * - JD Isaacks
- * - Zeno Zeng
- * - Chris Hemp
- * - shankesgk2
- */
-return [
- 'year' => ':count年',
- 'y' => ':count年',
- 'month' => ':count个月',
- 'm' => ':count个月',
- 'week' => ':count周',
- 'w' => ':count周',
- 'day' => ':count天',
- 'd' => ':count天',
- 'hour' => ':count小时',
- 'h' => ':count小时',
- 'minute' => ':count分钟',
- 'min' => ':count分钟',
- 'second' => ':count秒',
- 'a_second' => '{1}几秒|]1,Inf[:count秒',
- 's' => ':count秒',
- 'ago' => ':time前',
- 'from_now' => ':time内',
- 'after' => ':time后',
- 'before' => ':time前',
- 'diff_yesterday' => '昨天',
- 'diff_tomorrow' => '明天',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY年M月D日',
- 'LLL' => 'YYYY年M月D日Ah点mm分',
- 'LLLL' => 'YYYY年M月D日ddddAh点mm分',
- ],
- 'calendar' => [
- 'sameDay' => '[今天]LT',
- 'nextDay' => '[明天]LT',
- 'nextWeek' => '[下]ddddLT',
- 'lastDay' => '[昨天]LT',
- 'lastWeek' => '[上]ddddLT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'日';
- case 'M':
- return $number.'月';
- case 'w':
- case 'W':
- return $number.'周';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour, $minute) {
- $time = $hour * 100 + $minute;
- if ($time < 600) {
- return '凌晨';
- }
- if ($time < 900) {
- return '早上';
- }
- if ($time < 1130) {
- return '上午';
- }
- if ($time < 1230) {
- return '中午';
- }
- if ($time < 1800) {
- return '下午';
- }
-
- return '晚上';
- },
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => '',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - monkeycon
- * - François B
- * - Jason Katz-Brown
- * - Konstantin Konev
- * - Chris Lam
- * - Serhan Apaydın
- * - Gary Lo
- * - JD Isaacks
- * - Chris Hemp
- * - shankesgk2
- */
-return [
- 'year' => ':count年',
- 'y' => ':count年',
- 'month' => ':count個月',
- 'm' => ':count月',
- 'week' => ':count週',
- 'w' => ':count週',
- 'day' => ':count天',
- 'd' => ':count天',
- 'hour' => ':count小時',
- 'h' => ':count小時',
- 'minute' => ':count分鐘',
- 'min' => ':count分鐘',
- 'second' => ':count秒',
- 'a_second' => '{1}幾秒|]1,Inf[:count秒',
- 's' => ':count秒',
- 'ago' => ':time前',
- 'from_now' => ':time內',
- 'after' => ':time后',
- 'before' => ':time前',
- 'diff_yesterday' => '昨天',
- 'diff_tomorrow' => '明天',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY年M月D日',
- 'LLL' => 'YYYY年M月D日 HH:mm',
- 'LLLL' => 'YYYY年M月D日dddd HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[今天]LT',
- 'nextDay' => '[明天]LT',
- 'nextWeek' => '[下]ddddLT',
- 'lastDay' => '[昨天]LT',
- 'lastWeek' => '[上]ddddLT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'日';
- case 'M':
- return $number.'月';
- case 'w':
- case 'W':
- return $number.'周';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour, $minute) {
- $time = $hour * 100 + $minute;
- if ($time < 600) {
- return '凌晨';
- }
- if ($time < 900) {
- return '早上';
- }
- if ($time < 1130) {
- return '上午';
- }
- if ($time < 1230) {
- return '中午';
- }
- if ($time < 1800) {
- return '下午';
- }
-
- return '晚上';
- },
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => '',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/zh_HK.php', [
- 'meridiem' => ['上午', '下午'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hans.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hans.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hans.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return array_replace_recursive(require __DIR__.'/zh_TW.php', [
- 'meridiem' => ['上午', '下午'],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hant.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-return require __DIR__.'/zh_Hant.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * Authors:
- * - tarunvelli
- * - Eddie
- * - KID
- * - shankesgk2
- */
-return [
- 'year' => ':count 年',
- 'y' => ':count年',
- 'month' => ':count 個月',
- 'm' => ':count個月',
- 'week' => ':count 周',
- 'w' => ':count周',
- 'day' => ':count 天',
- 'd' => ':count天',
- 'hour' => ':count 小時',
- 'h' => ':count小時',
- 'minute' => ':count 分鐘',
- 'min' => ':count分鐘',
- 'second' => ':count 秒',
- 'a_second' => '{1}幾秒|]1,Inf[:count 秒',
- 's' => ':count秒',
- 'ago' => ':time前',
- 'from_now' => ':time內',
- 'after' => ':time后',
- 'before' => ':time前',
- 'diff_yesterday' => '昨天',
- 'diff_tomorrow' => '明天',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY年M月D日',
- 'LLL' => 'YYYY年M月D日 HH:mm',
- 'LLLL' => 'YYYY年M月D日dddd HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[今天] LT',
- 'nextDay' => '[明天] LT',
- 'nextWeek' => '[下]dddd LT',
- 'lastDay' => '[昨天] LT',
- 'lastWeek' => '[上]dddd LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'日';
- case 'M':
- return $number.'月';
- case 'w':
- case 'W':
- return $number.'周';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour, $minute) {
- $time = $hour * 100 + $minute;
- if ($time < 600) {
- return '凌晨';
- }
- if ($time < 900) {
- return '早上';
- }
- if ($time < 1130) {
- return '上午';
- }
- if ($time < 1230) {
- return '中午';
- }
- if ($time < 1800) {
- return '下午';
- }
-
- return '晚上';
- },
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => '',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/zh.php', [
- 'formats' => [
- 'L' => 'YYYY年MM月DD日',
- ],
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'day_of_first_week_of_year' => 1,
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Adam
- * - monkeycon
- * - François B
- * - Jason Katz-Brown
- * - Chris Lam
- * - Serhan Apaydın
- * - Gary Lo
- * - JD Isaacks
- * - Chris Hemp
- * - Eddie
- * - KID
- * - shankesgk2
- */
-return [
- 'year' => ':count年',
- 'y' => ':count年',
- 'month' => ':count個月',
- 'm' => ':count月',
- 'week' => ':count週',
- 'w' => ':count週',
- 'day' => ':count天',
- 'd' => ':count天',
- 'hour' => ':count小時',
- 'h' => ':count小時',
- 'minute' => ':count分鐘',
- 'min' => ':count分鐘',
- 'second' => ':count秒',
- 'a_second' => '{1}幾秒|]1,Inf[:count秒',
- 's' => ':count秒',
- 'ago' => ':time前',
- 'from_now' => ':time內',
- 'after' => ':time後',
- 'before' => ':time前',
- 'diff_yesterday' => '昨天',
- 'diff_tomorrow' => '明天',
- 'formats' => [
- 'LT' => 'HH:mm',
- 'LTS' => 'HH:mm:ss',
- 'L' => 'YYYY/MM/DD',
- 'LL' => 'YYYY年M月D日',
- 'LLL' => 'YYYY年M月D日 HH:mm',
- 'LLLL' => 'YYYY年M月D日dddd HH:mm',
- ],
- 'calendar' => [
- 'sameDay' => '[今天] LT',
- 'nextDay' => '[明天] LT',
- 'nextWeek' => '[下]dddd LT',
- 'lastDay' => '[昨天] LT',
- 'lastWeek' => '[上]dddd LT',
- 'sameElse' => 'L',
- ],
- 'ordinal' => function ($number, $period) {
- switch ($period) {
- case 'd':
- case 'D':
- case 'DDD':
- return $number.'日';
- case 'M':
- return $number.'月';
- case 'w':
- case 'W':
- return $number.'周';
- default:
- return $number;
- }
- },
- 'meridiem' => function ($hour, $minute) {
- $time = $hour * 100 + $minute;
- if ($time < 600) {
- return '凌晨';
- }
- if ($time < 900) {
- return '早上';
- }
- if ($time < 1130) {
- return '上午';
- }
- if ($time < 1230) {
- return '中午';
- }
- if ($time < 1800) {
- return '下午';
- }
-
- return '晚上';
- },
- 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
- 'weekdays_short' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
- 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
- 'first_day_of_week' => 1,
- 'day_of_first_week_of_year' => 4,
- 'list' => '',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
- */
-return array_replace_recursive(require __DIR__.'/zh.php', [
- 'formats' => [
- 'L' => 'YYYY-MM-DD',
- ],
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Unknown default region, use the first alphabetically.
- */
-return require __DIR__.'/zu_ZA.php';
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Authors:
- * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
- */
-return array_replace_recursive(require __DIR__.'/en.php', [
- 'formats' => [
- 'L' => 'DD/MM/YYYY',
- ],
- 'months' => ['Januwari', 'Februwari', 'Mashi', 'Ephreli', 'Meyi', 'Juni', 'Julayi', 'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
- 'months_short' => ['Jan', 'Feb', 'Mas', 'Eph', 'Mey', 'Jun', 'Jul', 'Aga', 'Sep', 'Okt', 'Nov', 'Dis'],
- 'weekdays' => ['iSonto', 'uMsombuluko', 'uLwesibili', 'uLwesithathu', 'uLwesine', 'uLwesihlanu', 'uMgqibelo'],
- 'weekdays_short' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
- 'weekdays_min' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
- 'day_of_first_week_of_year' => 1,
-
- 'year' => 'kweminyaka engu-:count',
- 'y' => 'kweminyaka engu-:count',
- 'a_year' => 'kweminyaka engu-:count',
-
- 'month' => 'izinyanga ezingu-:count',
- 'm' => 'izinyanga ezingu-:count',
- 'a_month' => 'izinyanga ezingu-:count',
-
- 'week' => 'lwamasonto angu-:count',
- 'w' => 'lwamasonto angu-:count',
- 'a_week' => 'lwamasonto angu-:count',
-
- 'day' => 'ezingaba ngu-:count',
- 'd' => 'ezingaba ngu-:count',
- 'a_day' => 'ezingaba ngu-:count',
-
- 'hour' => 'amahora angu-:count',
- 'h' => 'amahora angu-:count',
- 'a_hour' => 'amahora angu-:count',
-
- 'minute' => 'ngemizuzu engu-:count',
- 'min' => 'ngemizuzu engu-:count',
- 'a_minute' => 'ngemizuzu engu-:count',
-
- 'second' => 'imizuzwana engu-:count',
- 's' => 'imizuzwana engu-:count',
- 'a_second' => 'imizuzwana engu-:count',
-]);
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use JsonSerializable;
-
-class Language implements JsonSerializable
-{
- /**
- * @var array
- */
- protected static $languagesNames;
-
- /**
- * @var array
- */
- protected static $regionsNames;
-
- /**
- * @var string
- */
- protected $id;
-
- /**
- * @var string
- */
- protected $code;
-
- /**
- * @var string|null
- */
- protected $variant;
-
- /**
- * @var string|null
- */
- protected $region;
-
- /**
- * @var array
- */
- protected $names;
-
- /**
- * @var string
- */
- protected $isoName;
-
- /**
- * @var string
- */
- protected $nativeName;
-
- public function __construct(string $id)
- {
- $this->id = str_replace('-', '_', $id);
- $parts = explode('_', $this->id);
- $this->code = $parts[0];
-
- if (isset($parts[1])) {
- if (!preg_match('/^[A-Z]+$/', $parts[1])) {
- $this->variant = $parts[1];
- $parts[1] = $parts[2] ?? null;
- }
- if ($parts[1]) {
- $this->region = $parts[1];
- }
- }
- }
-
- /**
- * Get the list of the known languages.
- *
- * @return array
- */
- public static function all()
- {
- if (!static::$languagesNames) {
- static::$languagesNames = include __DIR__.'/List/languages.php';
- }
-
- return static::$languagesNames;
- }
-
- /**
- * Get the list of the known regions.
- *
- * @return array
- */
- public static function regions()
- {
- if (!static::$regionsNames) {
- static::$regionsNames = include __DIR__.'/List/regions.php';
- }
-
- return static::$regionsNames;
- }
-
- /**
- * Get both isoName and nativeName as an array.
- *
- * @return array
- */
- public function getNames(): array
- {
- if (!$this->names) {
- $this->names = static::all()[$this->code] ?? [
- 'isoName' => $this->code,
- 'nativeName' => $this->code,
- ];
- }
-
- return $this->names;
- }
-
- /**
- * Returns the original locale ID.
- *
- * @return string
- */
- public function getId(): string
- {
- return $this->id;
- }
-
- /**
- * Returns the code of the locale "en"/"fr".
- *
- * @return string
- */
- public function getCode(): string
- {
- return $this->code;
- }
-
- /**
- * Returns the variant code such as cyrl/latn.
- *
- * @return string|null
- */
- public function getVariant(): ?string
- {
- return $this->variant;
- }
-
- /**
- * Returns the variant such as Cyrillic/Latin.
- *
- * @return string|null
- */
- public function getVariantName(): ?string
- {
- if ($this->variant === 'Latn') {
- return 'Latin';
- }
-
- if ($this->variant === 'Cyrl') {
- return 'Cyrillic';
- }
-
- return $this->variant;
- }
-
- /**
- * Returns the region part of the locale.
- *
- * @return string|null
- */
- public function getRegion(): ?string
- {
- return $this->region;
- }
-
- /**
- * Returns the region name for the current language.
- *
- * @return string|null
- */
- public function getRegionName(): ?string
- {
- return $this->region ? (static::regions()[$this->region] ?? $this->region) : null;
- }
-
- /**
- * Returns the long ISO language name.
- *
- * @return string
- */
- public function getFullIsoName(): string
- {
- if (!$this->isoName) {
- $this->isoName = $this->getNames()['isoName'];
- }
-
- return $this->isoName;
- }
-
- /**
- * Set the ISO language name.
- *
- * @param string $isoName
- */
- public function setIsoName(string $isoName): self
- {
- $this->isoName = $isoName;
-
- return $this;
- }
-
- /**
- * Return the full name of the language in this language.
- *
- * @return string
- */
- public function getFullNativeName(): string
- {
- if (!$this->nativeName) {
- $this->nativeName = $this->getNames()['nativeName'];
- }
-
- return $this->nativeName;
- }
-
- /**
- * Set the name of the language in this language.
- *
- * @param string $nativeName
- */
- public function setNativeName(string $nativeName): self
- {
- $this->nativeName = $nativeName;
-
- return $this;
- }
-
- /**
- * Returns the short ISO language name.
- *
- * @return string
- */
- public function getIsoName(): string
- {
- $name = $this->getFullIsoName();
-
- return trim(strstr($name, ',', true) ?: $name);
- }
-
- /**
- * Get the short name of the language in this language.
- *
- * @return string
- */
- public function getNativeName(): string
- {
- $name = $this->getFullNativeName();
-
- return trim(strstr($name, ',', true) ?: $name);
- }
-
- /**
- * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
- *
- * @return string
- */
- public function getIsoDescription()
- {
- $region = $this->getRegionName();
- $variant = $this->getVariantName();
-
- return $this->getIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
- }
-
- /**
- * Get a string with short native name, region in parentheses if applicable, variant in parentheses if applicable.
- *
- * @return string
- */
- public function getNativeDescription()
- {
- $region = $this->getRegionName();
- $variant = $this->getVariantName();
-
- return $this->getNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
- }
-
- /**
- * Get a string with long ISO name, region in parentheses if applicable, variant in parentheses if applicable.
- *
- * @return string
- */
- public function getFullIsoDescription()
- {
- $region = $this->getRegionName();
- $variant = $this->getVariantName();
-
- return $this->getFullIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
- }
-
- /**
- * Get a string with long native name, region in parentheses if applicable, variant in parentheses if applicable.
- *
- * @return string
- */
- public function getFullNativeDescription()
- {
- $region = $this->getRegionName();
- $variant = $this->getVariantName();
-
- return $this->getFullNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
- }
-
- /**
- * Returns the original locale ID.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->getId();
- }
-
- /**
- * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
- *
- * @return string
- */
- public function jsonSerialize()
- {
- return $this->getIsoDescription();
- }
-}
+++ /dev/null
-<?php
-
-namespace Carbon\Laravel;
-
-use Carbon\Carbon;
-use Illuminate\Events\Dispatcher;
-use Illuminate\Events\EventDispatcher;
-use Illuminate\Translation\Translator as IlluminateTranslator;
-use Symfony\Component\Translation\Translator;
-
-class ServiceProvider extends \Illuminate\Support\ServiceProvider
-{
- public function boot()
- {
- if (!$this->app->bound('events') || !$this->app->bound('translator')) {
- return;
- }
-
- $service = $this;
- $events = $this->app['events'];
-
- if ($events instanceof EventDispatcher || $events instanceof Dispatcher) {
- $events->listen(class_exists('Illuminate\Foundation\Events\LocaleUpdated') ? 'Illuminate\Foundation\Events\LocaleUpdated' : 'locale.changed', function () use ($service) {
- $service->updateLocale();
- });
- $service->updateLocale();
- }
- }
-
- public function updateLocale()
- {
- $translator = $this->app['translator'];
-
- if ($translator instanceof Translator || $translator instanceof IlluminateTranslator) {
- Carbon::setLocale($translator->getLocale());
- }
- }
-
- public function register()
- {
- // Needed for Laravel < 5.3 compatibility
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-return [
- /*
- * ISO 639-2
- */
- 'ab' => [
- 'isoName' => 'Abkhazian',
- 'nativeName' => 'аҧсуа бызшәа, аҧсшәа',
- ],
- 'aa' => [
- 'isoName' => 'Afar',
- 'nativeName' => 'Afaraf',
- ],
- 'af' => [
- 'isoName' => 'Afrikaans',
- 'nativeName' => 'Afrikaans',
- ],
- 'ak' => [
- 'isoName' => 'Akan',
- 'nativeName' => 'Akan',
- ],
- 'sq' => [
- 'isoName' => 'Albanian',
- 'nativeName' => 'Shqip',
- ],
- 'am' => [
- 'isoName' => 'Amharic',
- 'nativeName' => 'አማርኛ',
- ],
- 'ar' => [
- 'isoName' => 'Arabic',
- 'nativeName' => 'العربية',
- ],
- 'an' => [
- 'isoName' => 'Aragonese',
- 'nativeName' => 'aragonés',
- ],
- 'hy' => [
- 'isoName' => 'Armenian',
- 'nativeName' => 'Հայերեն',
- ],
- 'as' => [
- 'isoName' => 'Assamese',
- 'nativeName' => 'অসমীয়া',
- ],
- 'av' => [
- 'isoName' => 'Avaric',
- 'nativeName' => 'авар мацӀ, магӀарул мацӀ',
- ],
- 'ae' => [
- 'isoName' => 'Avestan',
- 'nativeName' => 'avesta',
- ],
- 'ay' => [
- 'isoName' => 'Aymara',
- 'nativeName' => 'aymar aru',
- ],
- 'az' => [
- 'isoName' => 'Azerbaijani',
- 'nativeName' => 'azərbaycan dili',
- ],
- 'bm' => [
- 'isoName' => 'Bambara',
- 'nativeName' => 'bamanankan',
- ],
- 'ba' => [
- 'isoName' => 'Bashkir',
- 'nativeName' => 'башҡорт теле',
- ],
- 'eu' => [
- 'isoName' => 'Basque',
- 'nativeName' => 'euskara, euskera',
- ],
- 'be' => [
- 'isoName' => 'Belarusian',
- 'nativeName' => 'беларуская мова',
- ],
- 'bn' => [
- 'isoName' => 'Bengali',
- 'nativeName' => 'বাংলা',
- ],
- 'bh' => [
- 'isoName' => 'Bihari languages',
- 'nativeName' => 'भोजपुरी',
- ],
- 'bi' => [
- 'isoName' => 'Bislama',
- 'nativeName' => 'Bislama',
- ],
- 'bs' => [
- 'isoName' => 'Bosnian',
- 'nativeName' => 'bosanski jezik',
- ],
- 'br' => [
- 'isoName' => 'Breton',
- 'nativeName' => 'brezhoneg',
- ],
- 'bg' => [
- 'isoName' => 'Bulgarian',
- 'nativeName' => 'български език',
- ],
- 'my' => [
- 'isoName' => 'Burmese',
- 'nativeName' => 'ဗမာစာ',
- ],
- 'ca' => [
- 'isoName' => 'Catalan, Valencian',
- 'nativeName' => 'català, valencià',
- ],
- 'ch' => [
- 'isoName' => 'Chamorro',
- 'nativeName' => 'Chamoru',
- ],
- 'ce' => [
- 'isoName' => 'Chechen',
- 'nativeName' => 'нохчийн мотт',
- ],
- 'ny' => [
- 'isoName' => 'Chichewa, Chewa, Nyanja',
- 'nativeName' => 'chiCheŵa, chinyanja',
- ],
- 'zh' => [
- 'isoName' => 'Chinese',
- 'nativeName' => '中文 (Zhōngwén), 汉语, 漢語',
- ],
- 'cv' => [
- 'isoName' => 'Chuvash',
- 'nativeName' => 'чӑваш чӗлхи',
- ],
- 'kw' => [
- 'isoName' => 'Cornish',
- 'nativeName' => 'Kernewek',
- ],
- 'co' => [
- 'isoName' => 'Corsican',
- 'nativeName' => 'corsu, lingua corsa',
- ],
- 'cr' => [
- 'isoName' => 'Cree',
- 'nativeName' => 'ᓀᐦᐃᔭᐍᐏᐣ',
- ],
- 'hr' => [
- 'isoName' => 'Croatian',
- 'nativeName' => 'hrvatski jezik',
- ],
- 'cs' => [
- 'isoName' => 'Czech',
- 'nativeName' => 'čeština, český jazyk',
- ],
- 'da' => [
- 'isoName' => 'Danish',
- 'nativeName' => 'dansk',
- ],
- 'dv' => [
- 'isoName' => 'Divehi, Dhivehi, Maldivian',
- 'nativeName' => 'ދިވެހި',
- ],
- 'nl' => [
- 'isoName' => 'Dutch, Flemish',
- 'nativeName' => 'Nederlands, Vlaams',
- ],
- 'dz' => [
- 'isoName' => 'Dzongkha',
- 'nativeName' => 'རྫོང་ཁ',
- ],
- 'en' => [
- 'isoName' => 'English',
- 'nativeName' => 'English',
- ],
- 'eo' => [
- 'isoName' => 'Esperanto',
- 'nativeName' => 'Esperanto',
- ],
- 'et' => [
- 'isoName' => 'Estonian',
- 'nativeName' => 'eesti, eesti keel',
- ],
- 'ee' => [
- 'isoName' => 'Ewe',
- 'nativeName' => 'Eʋegbe',
- ],
- 'fo' => [
- 'isoName' => 'Faroese',
- 'nativeName' => 'føroyskt',
- ],
- 'fj' => [
- 'isoName' => 'Fijian',
- 'nativeName' => 'vosa Vakaviti',
- ],
- 'fi' => [
- 'isoName' => 'Finnish',
- 'nativeName' => 'suomi, suomen kieli',
- ],
- 'fr' => [
- 'isoName' => 'French',
- 'nativeName' => 'français',
- ],
- 'ff' => [
- 'isoName' => 'Fulah',
- 'nativeName' => 'Fulfulde, Pulaar, Pular',
- ],
- 'gl' => [
- 'isoName' => 'Galician',
- 'nativeName' => 'Galego',
- ],
- 'ka' => [
- 'isoName' => 'Georgian',
- 'nativeName' => 'ქართული',
- ],
- 'de' => [
- 'isoName' => 'German',
- 'nativeName' => 'Deutsch',
- ],
- 'el' => [
- 'isoName' => 'Greek (modern)',
- 'nativeName' => 'ελληνικά',
- ],
- 'gn' => [
- 'isoName' => 'Guaraní',
- 'nativeName' => 'Avañe\'ẽ',
- ],
- 'gu' => [
- 'isoName' => 'Gujarati',
- 'nativeName' => 'ગુજરાતી',
- ],
- 'ht' => [
- 'isoName' => 'Haitian, Haitian Creole',
- 'nativeName' => 'Kreyòl ayisyen',
- ],
- 'ha' => [
- 'isoName' => 'Hausa',
- 'nativeName' => '(Hausa) هَوُسَ',
- ],
- 'he' => [
- 'isoName' => 'Hebrew (modern)',
- 'nativeName' => 'עברית',
- ],
- 'hz' => [
- 'isoName' => 'Herero',
- 'nativeName' => 'Otjiherero',
- ],
- 'hi' => [
- 'isoName' => 'Hindi',
- 'nativeName' => 'हिन्दी, हिंदी',
- ],
- 'ho' => [
- 'isoName' => 'Hiri Motu',
- 'nativeName' => 'Hiri Motu',
- ],
- 'hu' => [
- 'isoName' => 'Hungarian',
- 'nativeName' => 'magyar',
- ],
- 'ia' => [
- 'isoName' => 'Interlingua',
- 'nativeName' => 'Interlingua',
- ],
- 'id' => [
- 'isoName' => 'Indonesian',
- 'nativeName' => 'Bahasa Indonesia',
- ],
- 'ie' => [
- 'isoName' => 'Interlingue',
- 'nativeName' => 'Originally called Occidental; then Interlingue after WWII',
- ],
- 'ga' => [
- 'isoName' => 'Irish',
- 'nativeName' => 'Gaeilge',
- ],
- 'ig' => [
- 'isoName' => 'Igbo',
- 'nativeName' => 'Asụsụ Igbo',
- ],
- 'ik' => [
- 'isoName' => 'Inupiaq',
- 'nativeName' => 'Iñupiaq, Iñupiatun',
- ],
- 'io' => [
- 'isoName' => 'Ido',
- 'nativeName' => 'Ido',
- ],
- 'is' => [
- 'isoName' => 'Icelandic',
- 'nativeName' => 'Íslenska',
- ],
- 'it' => [
- 'isoName' => 'Italian',
- 'nativeName' => 'Italiano',
- ],
- 'iu' => [
- 'isoName' => 'Inuktitut',
- 'nativeName' => 'ᐃᓄᒃᑎᑐᑦ',
- ],
- 'ja' => [
- 'isoName' => 'Japanese',
- 'nativeName' => '日本語 (にほんご)',
- ],
- 'jv' => [
- 'isoName' => 'Javanese',
- 'nativeName' => 'ꦧꦱꦗꦮ, Basa Jawa',
- ],
- 'kl' => [
- 'isoName' => 'Kalaallisut, Greenlandic',
- 'nativeName' => 'kalaallisut, kalaallit oqaasii',
- ],
- 'kn' => [
- 'isoName' => 'Kannada',
- 'nativeName' => 'ಕನ್ನಡ',
- ],
- 'kr' => [
- 'isoName' => 'Kanuri',
- 'nativeName' => 'Kanuri',
- ],
- 'ks' => [
- 'isoName' => 'Kashmiri',
- 'nativeName' => 'कश्मीरी, كشميري',
- ],
- 'kk' => [
- 'isoName' => 'Kazakh',
- 'nativeName' => 'қазақ тілі',
- ],
- 'km' => [
- 'isoName' => 'Central Khmer',
- 'nativeName' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ',
- ],
- 'ki' => [
- 'isoName' => 'Kikuyu, Gikuyu',
- 'nativeName' => 'Gĩkũyũ',
- ],
- 'rw' => [
- 'isoName' => 'Kinyarwanda',
- 'nativeName' => 'Ikinyarwanda',
- ],
- 'ky' => [
- 'isoName' => 'Kirghiz, Kyrgyz',
- 'nativeName' => 'Кыргызча, Кыргыз тили',
- ],
- 'kv' => [
- 'isoName' => 'Komi',
- 'nativeName' => 'коми кыв',
- ],
- 'kg' => [
- 'isoName' => 'Kongo',
- 'nativeName' => 'Kikongo',
- ],
- 'ko' => [
- 'isoName' => 'Korean',
- 'nativeName' => '한국어',
- ],
- 'ku' => [
- 'isoName' => 'Kurdish',
- 'nativeName' => 'Kurdî, کوردی',
- ],
- 'kj' => [
- 'isoName' => 'Kuanyama, Kwanyama',
- 'nativeName' => 'Kuanyama',
- ],
- 'la' => [
- 'isoName' => 'Latin',
- 'nativeName' => 'latine, lingua latina',
- ],
- 'lb' => [
- 'isoName' => 'Luxembourgish, Letzeburgesch',
- 'nativeName' => 'Lëtzebuergesch',
- ],
- 'lg' => [
- 'isoName' => 'Ganda',
- 'nativeName' => 'Luganda',
- ],
- 'li' => [
- 'isoName' => 'Limburgan, Limburger, Limburgish',
- 'nativeName' => 'Limburgs',
- ],
- 'ln' => [
- 'isoName' => 'Lingala',
- 'nativeName' => 'Lingála',
- ],
- 'lo' => [
- 'isoName' => 'Lao',
- 'nativeName' => 'ພາສາລາວ',
- ],
- 'lt' => [
- 'isoName' => 'Lithuanian',
- 'nativeName' => 'lietuvių kalba',
- ],
- 'lu' => [
- 'isoName' => 'Luba-Katanga',
- 'nativeName' => 'Kiluba',
- ],
- 'lv' => [
- 'isoName' => 'Latvian',
- 'nativeName' => 'latviešu valoda',
- ],
- 'gv' => [
- 'isoName' => 'Manx',
- 'nativeName' => 'Gaelg, Gailck',
- ],
- 'mk' => [
- 'isoName' => 'Macedonian',
- 'nativeName' => 'македонски јазик',
- ],
- 'mg' => [
- 'isoName' => 'Malagasy',
- 'nativeName' => 'fiteny malagasy',
- ],
- 'ms' => [
- 'isoName' => 'Malay',
- 'nativeName' => 'Bahasa Melayu, بهاس ملايو',
- ],
- 'ml' => [
- 'isoName' => 'Malayalam',
- 'nativeName' => 'മലയാളം',
- ],
- 'mt' => [
- 'isoName' => 'Maltese',
- 'nativeName' => 'Malti',
- ],
- 'mi' => [
- 'isoName' => 'Maori',
- 'nativeName' => 'te reo Māori',
- ],
- 'mr' => [
- 'isoName' => 'Marathi',
- 'nativeName' => 'मराठी',
- ],
- 'mh' => [
- 'isoName' => 'Marshallese',
- 'nativeName' => 'Kajin M̧ajeļ',
- ],
- 'mn' => [
- 'isoName' => 'Mongolian',
- 'nativeName' => 'Монгол хэл',
- ],
- 'na' => [
- 'isoName' => 'Nauru',
- 'nativeName' => 'Dorerin Naoero',
- ],
- 'nv' => [
- 'isoName' => 'Navajo, Navaho',
- 'nativeName' => 'Diné bizaad',
- ],
- 'nd' => [
- 'isoName' => 'North Ndebele',
- 'nativeName' => 'isiNdebele',
- ],
- 'ne' => [
- 'isoName' => 'Nepali',
- 'nativeName' => 'नेपाली',
- ],
- 'ng' => [
- 'isoName' => 'Ndonga',
- 'nativeName' => 'Owambo',
- ],
- 'nb' => [
- 'isoName' => 'Norwegian Bokmål',
- 'nativeName' => 'Norsk Bokmål',
- ],
- 'nn' => [
- 'isoName' => 'Norwegian Nynorsk',
- 'nativeName' => 'Norsk Nynorsk',
- ],
- 'no' => [
- 'isoName' => 'Norwegian',
- 'nativeName' => 'Norsk',
- ],
- 'ii' => [
- 'isoName' => 'Sichuan Yi, Nuosu',
- 'nativeName' => 'ꆈꌠ꒿ Nuosuhxop',
- ],
- 'nr' => [
- 'isoName' => 'South Ndebele',
- 'nativeName' => 'isiNdebele',
- ],
- 'oc' => [
- 'isoName' => 'Occitan',
- 'nativeName' => 'occitan, lenga d\'òc',
- ],
- 'oj' => [
- 'isoName' => 'Ojibwa',
- 'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
- ],
- 'cu' => [
- 'isoName' => 'Church Slavic, Church Slavonic, Old Church Slavonic, Old Slavonic, Old Bulgarian',
- 'nativeName' => 'ѩзыкъ словѣньскъ',
- ],
- 'om' => [
- 'isoName' => 'Oromo',
- 'nativeName' => 'Afaan Oromoo',
- ],
- 'or' => [
- 'isoName' => 'Oriya',
- 'nativeName' => 'ଓଡ଼ିଆ',
- ],
- 'os' => [
- 'isoName' => 'Ossetian, Ossetic',
- 'nativeName' => 'ирон æвзаг',
- ],
- 'pa' => [
- 'isoName' => 'Panjabi, Punjabi',
- 'nativeName' => 'ਪੰਜਾਬੀ',
- ],
- 'pi' => [
- 'isoName' => 'Pali',
- 'nativeName' => 'पाऴि',
- ],
- 'fa' => [
- 'isoName' => 'Persian',
- 'nativeName' => 'فارسی',
- ],
- 'pl' => [
- 'isoName' => 'Polish',
- 'nativeName' => 'język polski, polszczyzna',
- ],
- 'ps' => [
- 'isoName' => 'Pashto, Pushto',
- 'nativeName' => 'پښتو',
- ],
- 'pt' => [
- 'isoName' => 'Portuguese',
- 'nativeName' => 'Português',
- ],
- 'qu' => [
- 'isoName' => 'Quechua',
- 'nativeName' => 'Runa Simi, Kichwa',
- ],
- 'rm' => [
- 'isoName' => 'Romansh',
- 'nativeName' => 'Rumantsch Grischun',
- ],
- 'rn' => [
- 'isoName' => 'Rundi',
- 'nativeName' => 'Ikirundi',
- ],
- 'ro' => [
- 'isoName' => 'Romanian, Moldavian, Moldovan',
- 'nativeName' => 'Română',
- ],
- 'ru' => [
- 'isoName' => 'Russian',
- 'nativeName' => 'русский',
- ],
- 'sa' => [
- 'isoName' => 'Sanskrit',
- 'nativeName' => 'संस्कृतम्',
- ],
- 'sc' => [
- 'isoName' => 'Sardinian',
- 'nativeName' => 'sardu',
- ],
- 'sd' => [
- 'isoName' => 'Sindhi',
- 'nativeName' => 'सिन्धी, سنڌي، سندھی',
- ],
- 'se' => [
- 'isoName' => 'Northern Sami',
- 'nativeName' => 'Davvisámegiella',
- ],
- 'sm' => [
- 'isoName' => 'Samoan',
- 'nativeName' => 'gagana fa\'a Samoa',
- ],
- 'sg' => [
- 'isoName' => 'Sango',
- 'nativeName' => 'yângâ tî sängö',
- ],
- 'sr' => [
- 'isoName' => 'Serbian',
- 'nativeName' => 'српски језик',
- ],
- 'gd' => [
- 'isoName' => 'Gaelic, Scottish Gaelic',
- 'nativeName' => 'Gàidhlig',
- ],
- 'sn' => [
- 'isoName' => 'Shona',
- 'nativeName' => 'chiShona',
- ],
- 'si' => [
- 'isoName' => 'Sinhala, Sinhalese',
- 'nativeName' => 'සිංහල',
- ],
- 'sk' => [
- 'isoName' => 'Slovak',
- 'nativeName' => 'Slovenčina, Slovenský Jazyk',
- ],
- 'sl' => [
- 'isoName' => 'Slovene',
- 'nativeName' => 'Slovenski Jezik, Slovenščina',
- ],
- 'so' => [
- 'isoName' => 'Somali',
- 'nativeName' => 'Soomaaliga, af Soomaali',
- ],
- 'st' => [
- 'isoName' => 'Southern Sotho',
- 'nativeName' => 'Sesotho',
- ],
- 'es' => [
- 'isoName' => 'Spanish, Castilian',
- 'nativeName' => 'Español',
- ],
- 'su' => [
- 'isoName' => 'Sundanese',
- 'nativeName' => 'Basa Sunda',
- ],
- 'sw' => [
- 'isoName' => 'Swahili',
- 'nativeName' => 'Kiswahili',
- ],
- 'ss' => [
- 'isoName' => 'Swati',
- 'nativeName' => 'SiSwati',
- ],
- 'sv' => [
- 'isoName' => 'Swedish',
- 'nativeName' => 'Svenska',
- ],
- 'ta' => [
- 'isoName' => 'Tamil',
- 'nativeName' => 'தமிழ்',
- ],
- 'te' => [
- 'isoName' => 'Telugu',
- 'nativeName' => 'తెలుగు',
- ],
- 'tg' => [
- 'isoName' => 'Tajik',
- 'nativeName' => 'тоҷикӣ, toçikī, تاجیکی',
- ],
- 'th' => [
- 'isoName' => 'Thai',
- 'nativeName' => 'ไทย',
- ],
- 'ti' => [
- 'isoName' => 'Tigrinya',
- 'nativeName' => 'ትግርኛ',
- ],
- 'bo' => [
- 'isoName' => 'Tibetan',
- 'nativeName' => 'བོད་ཡིག',
- ],
- 'tk' => [
- 'isoName' => 'Turkmen',
- 'nativeName' => 'Türkmen, Түркмен',
- ],
- 'tl' => [
- 'isoName' => 'Tagalog',
- 'nativeName' => 'Wikang Tagalog',
- ],
- 'tn' => [
- 'isoName' => 'Tswana',
- 'nativeName' => 'Setswana',
- ],
- 'to' => [
- 'isoName' => 'Tongan (Tonga Islands)',
- 'nativeName' => 'Faka Tonga',
- ],
- 'tr' => [
- 'isoName' => 'Turkish',
- 'nativeName' => 'Türkçe',
- ],
- 'ts' => [
- 'isoName' => 'Tsonga',
- 'nativeName' => 'Xitsonga',
- ],
- 'tt' => [
- 'isoName' => 'Tatar',
- 'nativeName' => 'татар теле, tatar tele',
- ],
- 'tw' => [
- 'isoName' => 'Twi',
- 'nativeName' => 'Twi',
- ],
- 'ty' => [
- 'isoName' => 'Tahitian',
- 'nativeName' => 'Reo Tahiti',
- ],
- 'ug' => [
- 'isoName' => 'Uighur, Uyghur',
- 'nativeName' => 'Uyƣurqə, ئۇيغۇرچ',
- ],
- 'uk' => [
- 'isoName' => 'Ukrainian',
- 'nativeName' => 'Українська',
- ],
- 'ur' => [
- 'isoName' => 'Urdu',
- 'nativeName' => 'اردو',
- ],
- 'uz' => [
- 'isoName' => 'Uzbek',
- 'nativeName' => 'Oʻzbek, Ўзбек, أۇزبېك',
- ],
- 've' => [
- 'isoName' => 'Venda',
- 'nativeName' => 'Tshivenḓa',
- ],
- 'vi' => [
- 'isoName' => 'Vietnamese',
- 'nativeName' => 'Tiếng Việt',
- ],
- 'vo' => [
- 'isoName' => 'Volapük',
- 'nativeName' => 'Volapük',
- ],
- 'wa' => [
- 'isoName' => 'Walloon',
- 'nativeName' => 'Walon',
- ],
- 'cy' => [
- 'isoName' => 'Welsh',
- 'nativeName' => 'Cymraeg',
- ],
- 'wo' => [
- 'isoName' => 'Wolof',
- 'nativeName' => 'Wollof',
- ],
- 'fy' => [
- 'isoName' => 'Western Frisian',
- 'nativeName' => 'Frysk',
- ],
- 'xh' => [
- 'isoName' => 'Xhosa',
- 'nativeName' => 'isiXhosa',
- ],
- 'yi' => [
- 'isoName' => 'Yiddish',
- 'nativeName' => 'ייִדיש',
- ],
- 'yo' => [
- 'isoName' => 'Yoruba',
- 'nativeName' => 'Yorùbá',
- ],
- 'za' => [
- 'isoName' => 'Zhuang, Chuang',
- 'nativeName' => 'Saɯ cueŋƅ, Saw cuengh',
- ],
- 'zu' => [
- 'isoName' => 'Zulu',
- 'nativeName' => 'isiZulu',
- ],
- /*
- * Add ISO 639-3 languages available in Carbon
- */
- 'agq' => [
- 'isoName' => 'Aghem',
- 'nativeName' => 'Aghem',
- ],
- 'agr' => [
- 'isoName' => 'Aguaruna',
- 'nativeName' => 'Aguaruna',
- ],
- 'anp' => [
- 'isoName' => 'Angika',
- 'nativeName' => 'Angika',
- ],
- 'asa' => [
- 'isoName' => 'Asu',
- 'nativeName' => 'Asu',
- ],
- 'ast' => [
- 'isoName' => 'Asturian',
- 'nativeName' => 'Asturian',
- ],
- 'ayc' => [
- 'isoName' => 'Southern Aymara',
- 'nativeName' => 'Southern Aymara',
- ],
- 'bas' => [
- 'isoName' => 'Basaa',
- 'nativeName' => 'Basaa',
- ],
- 'bem' => [
- 'isoName' => 'Bemba',
- 'nativeName' => 'Bemba',
- ],
- 'bez' => [
- 'isoName' => 'Bena',
- 'nativeName' => 'Bena',
- ],
- 'bhb' => [
- 'isoName' => 'Bhili',
- 'nativeName' => 'Bhili',
- ],
- 'bho' => [
- 'isoName' => 'Bhojpuri',
- 'nativeName' => 'Bhojpuri',
- ],
- 'brx' => [
- 'isoName' => 'Bodo',
- 'nativeName' => 'Bodo',
- ],
- 'byn' => [
- 'isoName' => 'Bilin',
- 'nativeName' => 'Bilin',
- ],
- 'ccp' => [
- 'isoName' => 'Chakma',
- 'nativeName' => 'Chakma',
- ],
- 'cgg' => [
- 'isoName' => 'Chiga',
- 'nativeName' => 'Chiga',
- ],
- 'chr' => [
- 'isoName' => 'Cherokee',
- 'nativeName' => 'Cherokee',
- ],
- 'cmn' => [
- 'isoName' => 'Chinese',
- 'nativeName' => 'Chinese',
- ],
- 'crh' => [
- 'isoName' => 'Crimean Turkish',
- 'nativeName' => 'Crimean Turkish',
- ],
- 'csb' => [
- 'isoName' => 'Kashubian',
- 'nativeName' => 'Kashubian',
- ],
- 'dav' => [
- 'isoName' => 'Taita',
- 'nativeName' => 'Taita',
- ],
- 'dje' => [
- 'isoName' => 'Zarma',
- 'nativeName' => 'Zarma',
- ],
- 'doi' => [
- 'isoName' => 'Dogri (macrolanguage)',
- 'nativeName' => 'Dogri (macrolanguage)',
- ],
- 'dsb' => [
- 'isoName' => 'Lower Sorbian',
- 'nativeName' => 'Lower Sorbian',
- ],
- 'dua' => [
- 'isoName' => 'Duala',
- 'nativeName' => 'Duala',
- ],
- 'dyo' => [
- 'isoName' => 'Jola-Fonyi',
- 'nativeName' => 'Jola-Fonyi',
- ],
- 'ebu' => [
- 'isoName' => 'Embu',
- 'nativeName' => 'Embu',
- ],
- 'ewo' => [
- 'isoName' => 'Ewondo',
- 'nativeName' => 'Ewondo',
- ],
- 'fil' => [
- 'isoName' => 'Filipino',
- 'nativeName' => 'Filipino',
- ],
- 'fur' => [
- 'isoName' => 'Friulian',
- 'nativeName' => 'Friulian',
- ],
- 'gez' => [
- 'isoName' => 'Geez',
- 'nativeName' => 'Geez',
- ],
- 'gom' => [
- 'isoName' => 'Konkani, Goan',
- 'nativeName' => 'ಕೊಂಕಣಿ',
- ],
- 'gsw' => [
- 'isoName' => 'Swiss German',
- 'nativeName' => 'Swiss German',
- ],
- 'guz' => [
- 'isoName' => 'Gusii',
- 'nativeName' => 'Gusii',
- ],
- 'hak' => [
- 'isoName' => 'Hakka Chinese',
- 'nativeName' => 'Hakka Chinese',
- ],
- 'haw' => [
- 'isoName' => 'Hawaiian',
- 'nativeName' => 'Hawaiian',
- ],
- 'hif' => [
- 'isoName' => 'Fiji Hindi',
- 'nativeName' => 'Fiji Hindi',
- ],
- 'hne' => [
- 'isoName' => 'Chhattisgarhi',
- 'nativeName' => 'Chhattisgarhi',
- ],
- 'hsb' => [
- 'isoName' => 'Upper Sorbian',
- 'nativeName' => 'Upper Sorbian',
- ],
- 'jgo' => [
- 'isoName' => 'Ngomba',
- 'nativeName' => 'Ngomba',
- ],
- 'jmc' => [
- 'isoName' => 'Machame',
- 'nativeName' => 'Machame',
- ],
- 'kab' => [
- 'isoName' => 'Kabyle',
- 'nativeName' => 'Kabyle',
- ],
- 'kam' => [
- 'isoName' => 'Kamba',
- 'nativeName' => 'Kamba',
- ],
- 'kde' => [
- 'isoName' => 'Makonde',
- 'nativeName' => 'Makonde',
- ],
- 'kea' => [
- 'isoName' => 'Kabuverdianu',
- 'nativeName' => 'Kabuverdianu',
- ],
- 'khq' => [
- 'isoName' => 'Koyra Chiini',
- 'nativeName' => 'Koyra Chiini',
- ],
- 'kkj' => [
- 'isoName' => 'Kako',
- 'nativeName' => 'Kako',
- ],
- 'kln' => [
- 'isoName' => 'Kalenjin',
- 'nativeName' => 'Kalenjin',
- ],
- 'kok' => [
- 'isoName' => 'Konkani',
- 'nativeName' => 'Konkani',
- ],
- 'ksb' => [
- 'isoName' => 'Shambala',
- 'nativeName' => 'Shambala',
- ],
- 'ksf' => [
- 'isoName' => 'Bafia',
- 'nativeName' => 'Bafia',
- ],
- 'ksh' => [
- 'isoName' => 'Colognian',
- 'nativeName' => 'Colognian',
- ],
- 'lag' => [
- 'isoName' => 'Langi',
- 'nativeName' => 'Langi',
- ],
- 'lij' => [
- 'isoName' => 'Ligurian',
- 'nativeName' => 'Ligurian',
- ],
- 'lkt' => [
- 'isoName' => 'Lakota',
- 'nativeName' => 'Lakota',
- ],
- 'lrc' => [
- 'isoName' => 'Northern Luri',
- 'nativeName' => 'Northern Luri',
- ],
- 'luo' => [
- 'isoName' => 'Luo',
- 'nativeName' => 'Luo',
- ],
- 'luy' => [
- 'isoName' => 'Luyia',
- 'nativeName' => 'Luyia',
- ],
- 'lzh' => [
- 'isoName' => 'Literary Chinese',
- 'nativeName' => 'Literary Chinese',
- ],
- 'mag' => [
- 'isoName' => 'Magahi',
- 'nativeName' => 'Magahi',
- ],
- 'mai' => [
- 'isoName' => 'Maithili',
- 'nativeName' => 'Maithili',
- ],
- 'mas' => [
- 'isoName' => 'Masai',
- 'nativeName' => 'Masai',
- ],
- 'mer' => [
- 'isoName' => 'Meru',
- 'nativeName' => 'Meru',
- ],
- 'mfe' => [
- 'isoName' => 'Morisyen',
- 'nativeName' => 'Morisyen',
- ],
- 'mgh' => [
- 'isoName' => 'Makhuwa-Meetto',
- 'nativeName' => 'Makhuwa-Meetto',
- ],
- 'mgo' => [
- 'isoName' => 'Metaʼ',
- 'nativeName' => 'Metaʼ',
- ],
- 'mhr' => [
- 'isoName' => 'Eastern Mari',
- 'nativeName' => 'Eastern Mari',
- ],
- 'miq' => [
- 'isoName' => 'Mískito',
- 'nativeName' => 'Mískito',
- ],
- 'mjw' => [
- 'isoName' => 'Karbi',
- 'nativeName' => 'Karbi',
- ],
- 'mni' => [
- 'isoName' => 'Manipuri',
- 'nativeName' => 'Manipuri',
- ],
- 'mua' => [
- 'isoName' => 'Mundang',
- 'nativeName' => 'Mundang',
- ],
- 'mzn' => [
- 'isoName' => 'Mazanderani',
- 'nativeName' => 'Mazanderani',
- ],
- 'nan' => [
- 'isoName' => 'Min Nan Chinese',
- 'nativeName' => 'Min Nan Chinese',
- ],
- 'naq' => [
- 'isoName' => 'Nama',
- 'nativeName' => 'Nama',
- ],
- 'nds' => [
- 'isoName' => 'Low German',
- 'nativeName' => 'Low German',
- ],
- 'nhn' => [
- 'isoName' => 'Central Nahuatl',
- 'nativeName' => 'Central Nahuatl',
- ],
- 'niu' => [
- 'isoName' => 'Niuean',
- 'nativeName' => 'Niuean',
- ],
- 'nmg' => [
- 'isoName' => 'Kwasio',
- 'nativeName' => 'Kwasio',
- ],
- 'nnh' => [
- 'isoName' => 'Ngiemboon',
- 'nativeName' => 'Ngiemboon',
- ],
- 'nso' => [
- 'isoName' => 'Northern Sotho',
- 'nativeName' => 'Northern Sotho',
- ],
- 'nus' => [
- 'isoName' => 'Nuer',
- 'nativeName' => 'Nuer',
- ],
- 'nyn' => [
- 'isoName' => 'Nyankole',
- 'nativeName' => 'Nyankole',
- ],
- 'pap' => [
- 'isoName' => 'Papiamento',
- 'nativeName' => 'Papiamento',
- ],
- 'prg' => [
- 'isoName' => 'Prussian',
- 'nativeName' => 'Prussian',
- ],
- 'quz' => [
- 'isoName' => 'Cusco Quechua',
- 'nativeName' => 'Cusco Quechua',
- ],
- 'raj' => [
- 'isoName' => 'Rajasthani',
- 'nativeName' => 'Rajasthani',
- ],
- 'rof' => [
- 'isoName' => 'Rombo',
- 'nativeName' => 'Rombo',
- ],
- 'rwk' => [
- 'isoName' => 'Rwa',
- 'nativeName' => 'Rwa',
- ],
- 'sah' => [
- 'isoName' => 'Sakha',
- 'nativeName' => 'Sakha',
- ],
- 'saq' => [
- 'isoName' => 'Samburu',
- 'nativeName' => 'Samburu',
- ],
- 'sat' => [
- 'isoName' => 'Santali',
- 'nativeName' => 'Santali',
- ],
- 'sbp' => [
- 'isoName' => 'Sangu',
- 'nativeName' => 'Sangu',
- ],
- 'scr' => [
- 'isoName' => 'Serbo Croatian',
- 'nativeName' => 'Serbo Croatian',
- ],
- 'seh' => [
- 'isoName' => 'Sena',
- 'nativeName' => 'Sena',
- ],
- 'ses' => [
- 'isoName' => 'Koyraboro Senni',
- 'nativeName' => 'Koyraboro Senni',
- ],
- 'sgs' => [
- 'isoName' => 'Samogitian',
- 'nativeName' => 'Samogitian',
- ],
- 'shi' => [
- 'isoName' => 'Tachelhit',
- 'nativeName' => 'Tachelhit',
- ],
- 'shn' => [
- 'isoName' => 'Shan',
- 'nativeName' => 'Shan',
- ],
- 'shs' => [
- 'isoName' => 'Shuswap',
- 'nativeName' => 'Shuswap',
- ],
- 'sid' => [
- 'isoName' => 'Sidamo',
- 'nativeName' => 'Sidamo',
- ],
- 'smn' => [
- 'isoName' => 'Inari Sami',
- 'nativeName' => 'Inari Sami',
- ],
- 'szl' => [
- 'isoName' => 'Silesian',
- 'nativeName' => 'Silesian',
- ],
- 'tcy' => [
- 'isoName' => 'Tulu',
- 'nativeName' => 'Tulu',
- ],
- 'teo' => [
- 'isoName' => 'Teso',
- 'nativeName' => 'Teso',
- ],
- 'tet' => [
- 'isoName' => 'Tetum',
- 'nativeName' => 'Tetum',
- ],
- 'the' => [
- 'isoName' => 'Chitwania Tharu',
- 'nativeName' => 'Chitwania Tharu',
- ],
- 'tig' => [
- 'isoName' => 'Tigre',
- 'nativeName' => 'Tigre',
- ],
- 'tlh' => [
- 'isoName' => 'Klingon',
- 'nativeName' => 'tlhIngan Hol',
- ],
- 'tpi' => [
- 'isoName' => 'Tok Pisin',
- 'nativeName' => 'Tok Pisin',
- ],
- 'twq' => [
- 'isoName' => 'Tasawaq',
- 'nativeName' => 'Tasawaq',
- ],
- 'tzl' => [
- 'isoName' => 'Talossan',
- 'nativeName' => 'Talossan',
- ],
- 'tzm' => [
- 'isoName' => 'Tamazight, Central Atlas',
- 'nativeName' => 'ⵜⵎⴰⵣⵉⵖⵜ',
- ],
- 'unm' => [
- 'isoName' => 'Unami',
- 'nativeName' => 'Unami',
- ],
- 'vai' => [
- 'isoName' => 'Vai',
- 'nativeName' => 'Vai',
- ],
- 'vun' => [
- 'isoName' => 'Vunjo',
- 'nativeName' => 'Vunjo',
- ],
- 'wae' => [
- 'isoName' => 'Walser',
- 'nativeName' => 'Walser',
- ],
- 'wal' => [
- 'isoName' => 'Wolaytta',
- 'nativeName' => 'Wolaytta',
- ],
- 'xog' => [
- 'isoName' => 'Soga',
- 'nativeName' => 'Soga',
- ],
- 'yav' => [
- 'isoName' => 'Yangben',
- 'nativeName' => 'Yangben',
- ],
- 'yue' => [
- 'isoName' => 'Cantonese',
- 'nativeName' => 'Cantonese',
- ],
- 'yuw' => [
- 'isoName' => 'Yau (Morobe Province)',
- 'nativeName' => 'Yau (Morobe Province)',
- ],
- 'zgh' => [
- 'isoName' => 'Standard Moroccan Tamazight',
- 'nativeName' => 'Standard Moroccan Tamazight',
- ],
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * ISO 3166-2
- */
-return [
- 'AD' => 'Andorra',
- 'AE' => 'United Arab Emirates',
- 'AF' => 'Afghanistan',
- 'AG' => 'Antigua and Barbuda',
- 'AI' => 'Anguilla',
- 'AL' => 'Albania',
- 'AM' => 'Armenia',
- 'AO' => 'Angola',
- 'AQ' => 'Antarctica',
- 'AR' => 'Argentina',
- 'AS' => 'American Samoa',
- 'AT' => 'Austria',
- 'AU' => 'Australia',
- 'AW' => 'Aruba',
- 'AX' => 'Åland Islands',
- 'AZ' => 'Azerbaijan',
- 'BA' => 'Bosnia and Herzegovina',
- 'BB' => 'Barbados',
- 'BD' => 'Bangladesh',
- 'BE' => 'Belgium',
- 'BF' => 'Burkina Faso',
- 'BG' => 'Bulgaria',
- 'BH' => 'Bahrain',
- 'BI' => 'Burundi',
- 'BJ' => 'Benin',
- 'BL' => 'Saint Barthélemy',
- 'BM' => 'Bermuda',
- 'BN' => 'Brunei Darussalam',
- 'BO' => 'Bolivia (Plurinational State of)',
- 'BQ' => 'Bonaire, Sint Eustatius and Saba',
- 'BR' => 'Brazil',
- 'BS' => 'Bahamas',
- 'BT' => 'Bhutan',
- 'BV' => 'Bouvet Island',
- 'BW' => 'Botswana',
- 'BY' => 'Belarus',
- 'BZ' => 'Belize',
- 'CA' => 'Canada',
- 'CC' => 'Cocos (Keeling) Islands',
- 'CD' => 'Congo, Democratic Republic of the',
- 'CF' => 'Central African Republic',
- 'CG' => 'Congo',
- 'CH' => 'Switzerland',
- 'CI' => 'Côte d\'Ivoire',
- 'CK' => 'Cook Islands',
- 'CL' => 'Chile',
- 'CM' => 'Cameroon',
- 'CN' => 'China',
- 'CO' => 'Colombia',
- 'CR' => 'Costa Rica',
- 'CU' => 'Cuba',
- 'CV' => 'Cabo Verde',
- 'CW' => 'Curaçao',
- 'CX' => 'Christmas Island',
- 'CY' => 'Cyprus',
- 'CZ' => 'Czechia',
- 'DE' => 'Germany',
- 'DJ' => 'Djibouti',
- 'DK' => 'Denmark',
- 'DM' => 'Dominica',
- 'DO' => 'Dominican Republic',
- 'DZ' => 'Algeria',
- 'EC' => 'Ecuador',
- 'EE' => 'Estonia',
- 'EG' => 'Egypt',
- 'EH' => 'Western Sahara',
- 'ER' => 'Eritrea',
- 'ES' => 'Spain',
- 'ET' => 'Ethiopia',
- 'FI' => 'Finland',
- 'FJ' => 'Fiji',
- 'FK' => 'Falkland Islands (Malvinas)',
- 'FM' => 'Micronesia (Federated States of)',
- 'FO' => 'Faroe Islands',
- 'FR' => 'France',
- 'GA' => 'Gabon',
- 'GB' => 'United Kingdom of Great Britain and Northern Ireland',
- 'GD' => 'Grenada',
- 'GE' => 'Georgia',
- 'GF' => 'French Guiana',
- 'GG' => 'Guernsey',
- 'GH' => 'Ghana',
- 'GI' => 'Gibraltar',
- 'GL' => 'Greenland',
- 'GM' => 'Gambia',
- 'GN' => 'Guinea',
- 'GP' => 'Guadeloupe',
- 'GQ' => 'Equatorial Guinea',
- 'GR' => 'Greece',
- 'GS' => 'South Georgia and the South Sandwich Islands',
- 'GT' => 'Guatemala',
- 'GU' => 'Guam',
- 'GW' => 'Guinea-Bissau',
- 'GY' => 'Guyana',
- 'HK' => 'Hong Kong',
- 'HM' => 'Heard Island and McDonald Islands',
- 'HN' => 'Honduras',
- 'HR' => 'Croatia',
- 'HT' => 'Haiti',
- 'HU' => 'Hungary',
- 'ID' => 'Indonesia',
- 'IE' => 'Ireland',
- 'IL' => 'Israel',
- 'IM' => 'Isle of Man',
- 'IN' => 'India',
- 'IO' => 'British Indian Ocean Territory',
- 'IQ' => 'Iraq',
- 'IR' => 'Iran (Islamic Republic of)',
- 'IS' => 'Iceland',
- 'IT' => 'Italy',
- 'JE' => 'Jersey',
- 'JM' => 'Jamaica',
- 'JO' => 'Jordan',
- 'JP' => 'Japan',
- 'KE' => 'Kenya',
- 'KG' => 'Kyrgyzstan',
- 'KH' => 'Cambodia',
- 'KI' => 'Kiribati',
- 'KM' => 'Comoros',
- 'KN' => 'Saint Kitts and Nevis',
- 'KP' => 'Korea (Democratic People\'s Republic of)',
- 'KR' => 'Korea, Republic of',
- 'KW' => 'Kuwait',
- 'KY' => 'Cayman Islands',
- 'KZ' => 'Kazakhstan',
- 'LA' => 'Lao People\'s Democratic Republic',
- 'LB' => 'Lebanon',
- 'LC' => 'Saint Lucia',
- 'LI' => 'Liechtenstein',
- 'LK' => 'Sri Lanka',
- 'LR' => 'Liberia',
- 'LS' => 'Lesotho',
- 'LT' => 'Lithuania',
- 'LU' => 'Luxembourg',
- 'LV' => 'Latvia',
- 'LY' => 'Libya',
- 'MA' => 'Morocco',
- 'MC' => 'Monaco',
- 'MD' => 'Moldova, Republic of',
- 'ME' => 'Montenegro',
- 'MF' => 'Saint Martin (French part)',
- 'MG' => 'Madagascar',
- 'MH' => 'Marshall Islands',
- 'MK' => 'Macedonia, the former Yugoslav Republic of',
- 'ML' => 'Mali',
- 'MM' => 'Myanmar',
- 'MN' => 'Mongolia',
- 'MO' => 'Macao',
- 'MP' => 'Northern Mariana Islands',
- 'MQ' => 'Martinique',
- 'MR' => 'Mauritania',
- 'MS' => 'Montserrat',
- 'MT' => 'Malta',
- 'MU' => 'Mauritius',
- 'MV' => 'Maldives',
- 'MW' => 'Malawi',
- 'MX' => 'Mexico',
- 'MY' => 'Malaysia',
- 'MZ' => 'Mozambique',
- 'NA' => 'Namibia',
- 'NC' => 'New Caledonia',
- 'NE' => 'Niger',
- 'NF' => 'Norfolk Island',
- 'NG' => 'Nigeria',
- 'NI' => 'Nicaragua',
- 'NL' => 'Netherlands',
- 'NO' => 'Norway',
- 'NP' => 'Nepal',
- 'NR' => 'Nauru',
- 'NU' => 'Niue',
- 'NZ' => 'New Zealand',
- 'OM' => 'Oman',
- 'PA' => 'Panama',
- 'PE' => 'Peru',
- 'PF' => 'French Polynesia',
- 'PG' => 'Papua New Guinea',
- 'PH' => 'Philippines',
- 'PK' => 'Pakistan',
- 'PL' => 'Poland',
- 'PM' => 'Saint Pierre and Miquelon',
- 'PN' => 'Pitcairn',
- 'PR' => 'Puerto Rico',
- 'PS' => 'Palestine, State of',
- 'PT' => 'Portugal',
- 'PW' => 'Palau',
- 'PY' => 'Paraguay',
- 'QA' => 'Qatar',
- 'RE' => 'Réunion',
- 'RO' => 'Romania',
- 'RS' => 'Serbia',
- 'RU' => 'Russian Federation',
- 'RW' => 'Rwanda',
- 'SA' => 'Saudi Arabia',
- 'SB' => 'Solomon Islands',
- 'SC' => 'Seychelles',
- 'SD' => 'Sudan',
- 'SE' => 'Sweden',
- 'SG' => 'Singapore',
- 'SH' => 'Saint Helena, Ascension and Tristan da Cunha',
- 'SI' => 'Slovenia',
- 'SJ' => 'Svalbard and Jan Mayen',
- 'SK' => 'Slovakia',
- 'SL' => 'Sierra Leone',
- 'SM' => 'San Marino',
- 'SN' => 'Senegal',
- 'SO' => 'Somalia',
- 'SR' => 'Suriname',
- 'SS' => 'South Sudan',
- 'ST' => 'Sao Tome and Principe',
- 'SV' => 'El Salvador',
- 'SX' => 'Sint Maarten (Dutch part)',
- 'SY' => 'Syrian Arab Republic',
- 'SZ' => 'Eswatini',
- 'TC' => 'Turks and Caicos Islands',
- 'TD' => 'Chad',
- 'TF' => 'French Southern Territories',
- 'TG' => 'Togo',
- 'TH' => 'Thailand',
- 'TJ' => 'Tajikistan',
- 'TK' => 'Tokelau',
- 'TL' => 'Timor-Leste',
- 'TM' => 'Turkmenistan',
- 'TN' => 'Tunisia',
- 'TO' => 'Tonga',
- 'TR' => 'Turkey',
- 'TT' => 'Trinidad and Tobago',
- 'TV' => 'Tuvalu',
- 'TW' => 'Taiwan, Province of China',
- 'TZ' => 'Tanzania, United Republic of',
- 'UA' => 'Ukraine',
- 'UG' => 'Uganda',
- 'UM' => 'United States Minor Outlying Islands',
- 'US' => 'United States of America',
- 'UY' => 'Uruguay',
- 'UZ' => 'Uzbekistan',
- 'VA' => 'Holy See',
- 'VC' => 'Saint Vincent and the Grenadines',
- 'VE' => 'Venezuela (Bolivarian Republic of)',
- 'VG' => 'Virgin Islands (British)',
- 'VI' => 'Virgin Islands (U.S.)',
- 'VN' => 'Viet Nam',
- 'VU' => 'Vanuatu',
- 'WF' => 'Wallis and Futuna',
- 'WS' => 'Samoa',
- 'YE' => 'Yemen',
- 'YT' => 'Mayotte',
- 'ZA' => 'South Africa',
- 'ZM' => 'Zambia',
- 'ZW' => 'Zimbabwe',
-];
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-use InvalidArgumentException;
-
-/**
- * Trait Boundaries.
- *
- * startOf, endOf and derived method for each unit.
- *
- * Depends on the following properties:
- *
- * @property int $year
- * @property int $month
- * @property int $daysInMonth
- * @property int $quarter
- *
- * Depends on the following methods:
- *
- * @method $this setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0)
- * @method $this setDate(int $year, int $month, int $day)
- * @method $this addMonths(int $value = 1)
- */
-trait Boundaries
-{
- /**
- * Resets the time to 00:00:00 start of day
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfDay()
- {
- return $this->setTime(0, 0, 0, 0);
- }
-
- /**
- * Resets the time to 23:59:59.999999 end of day
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfDay()
- {
- return $this->setTime(static::HOURS_PER_DAY - 1, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
- }
-
- /**
- * Resets the date to the first day of the month and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfMonth()
- {
- return $this->setDate($this->year, $this->month, 1)->startOfDay();
- }
-
- /**
- * Resets the date to end of the month and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfMonth()
- {
- return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay();
- }
-
- /**
- * Resets the date to the first day of the quarter and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfQuarter()
- {
- $month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1;
-
- return $this->setDate($this->year, $month, 1)->startOfDay();
- }
-
- /**
- * Resets the date to end of the quarter and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfQuarter()
- {
- return $this->startOfQuarter()->addMonths(static::MONTHS_PER_QUARTER - 1)->endOfMonth();
- }
-
- /**
- * Resets the date to the first day of the year and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfYear()
- {
- return $this->setDate($this->year, 1, 1)->startOfDay();
- }
-
- /**
- * Resets the date to end of the year and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfYear()
- {
- return $this->setDate($this->year, 12, 31)->endOfDay();
- }
-
- /**
- * Resets the date to the first day of the decade and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfDecade()
- {
- $year = $this->year - $this->year % static::YEARS_PER_DECADE;
-
- return $this->setDate($year, 1, 1)->startOfDay();
- }
-
- /**
- * Resets the date to end of the decade and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfDecade()
- {
- $year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1;
-
- return $this->setDate($year, 12, 31)->endOfDay();
- }
-
- /**
- * Resets the date to the first day of the century and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfCentury()
- {
- $year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY;
-
- return $this->setDate($year, 1, 1)->startOfDay();
- }
-
- /**
- * Resets the date to end of the century and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfCentury()
- {
- $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY;
-
- return $this->setDate($year, 12, 31)->endOfDay();
- }
-
- /**
- * Resets the date to the first day of the century and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfMillennium()
- {
- $year = $this->year - ($this->year - 1) % static::YEARS_PER_MILLENNIUM;
-
- return $this->setDate($year, 1, 1)->startOfDay();
- }
-
- /**
- * Resets the date to end of the century and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfMillennium()
- {
- $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_MILLENNIUM + static::YEARS_PER_MILLENNIUM;
-
- return $this->setDate($year, 12, 31)->endOfDay();
- }
-
- /**
- * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n";
- * ```
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return static|CarbonInterface
- */
- public function startOfWeek($weekStartsAt = null)
- {
- $date = $this;
- while ($date->dayOfWeek !== ($weekStartsAt ?? $this->firstWeekDay)) {
- $date = $date->subDay();
- }
-
- return $date->startOfDay();
- }
-
- /**
- * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n";
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n";
- * ```
- *
- * @param int $weekEndsAt optional start allow you to specify the day of week to use to end the week
- *
- * @return static|CarbonInterface
- */
- public function endOfWeek($weekEndsAt = null)
- {
- $date = $this;
- while ($date->dayOfWeek !== ($weekEndsAt ?? $this->lastWeekDay)) {
- $date = $date->addDay();
- }
-
- return $date->endOfDay();
- }
-
- /**
- * Modify to start of current hour, minutes and seconds become 0
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfHour()
- {
- return $this->setTime($this->hour, 0, 0, 0);
- }
-
- /**
- * Modify to end of current hour, minutes and seconds become 59
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfHour()
- {
- return $this->setTime($this->hour, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
- }
-
- /**
- * Modify to start of current minute, seconds become 0
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfMinute()
- {
- return $this->setTime($this->hour, $this->minute, 0, 0);
- }
-
- /**
- * Modify to end of current minute, seconds become 59
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute();
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfMinute()
- {
- return $this->setTime($this->hour, $this->minute, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
- }
-
- /**
- * Modify to start of current second, microseconds become 0
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->startOfSecond()
- * ->format('H:i:s.u');
- * ```
- *
- * @return static|CarbonInterface
- */
- public function startOfSecond()
- {
- return $this->setTime($this->hour, $this->minute, $this->second, 0);
- }
-
- /**
- * Modify to end of current second, microseconds become 999999
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->endOfSecond()
- * ->format('H:i:s.u');
- * ```
- *
- * @return static|CarbonInterface
- */
- public function endOfSecond()
- {
- return $this->setTime($this->hour, $this->minute, $this->second, static::MICROSECONDS_PER_SECOND - 1);
- }
-
- /**
- * Modify to start of current given unit.
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->startOf('month')
- * ->endOf('week', Carbon::FRIDAY);
- * ```
- *
- * @param string $unit
- * @param array<int, mixed> $params
- *
- * @return static|CarbonInterface
- */
- public function startOf($unit, ...$params)
- {
- $ucfUnit = ucfirst(static::singularUnit($unit));
- $method = "startOf$ucfUnit";
- if (!method_exists($this, $method)) {
- throw new InvalidArgumentException("Unknown unit '$unit'");
- }
-
- return $this->$method(...$params);
- }
-
- /**
- * Modify to end of current given unit.
- *
- * @example
- * ```
- * echo Carbon::parse('2018-07-25 12:45:16.334455')
- * ->startOf('month')
- * ->endOf('week', Carbon::FRIDAY);
- * ```
- *
- * @param string $unit
- * @param array<int, mixed> $params
- *
- * @return static|CarbonInterface
- */
- public function endOf($unit, ...$params)
- {
- $ucfUnit = ucfirst(static::singularUnit($unit));
- $method = "endOf$ucfUnit";
- if (!method_exists($this, $method)) {
- throw new InvalidArgumentException("Unknown unit '$unit'");
- }
-
- return $this->$method(...$params);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-use DateTimeInterface;
-use InvalidArgumentException;
-
-/**
- * Trait Comparison.
- *
- * Comparison utils and testers. All the following methods return booleans.
- * nowWithSameTz
- *
- * Depends on the following methods:
- *
- * @method CarbonInterface nowWithSameTz()
- * @method static CarbonInterface yesterday($timezone = null)
- * @method static CarbonInterface tomorrow($timezone = null)
- */
-trait Comparison
-{
- /**
- * Determines if the instance is equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see equalTo()
- *
- * @return bool
- */
- public function eq($date): bool
- {
- return $this->equalTo($date);
- }
-
- /**
- * Determines if the instance is equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function equalTo($date): bool
- {
- return $this == $date;
- }
-
- /**
- * Determines if the instance is not equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see notEqualTo()
- *
- * @return bool
- */
- public function ne($date): bool
- {
- return $this->notEqualTo($date);
- }
-
- /**
- * Determines if the instance is not equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function notEqualTo($date): bool
- {
- return !$this->equalTo($date);
- }
-
- /**
- * Determines if the instance is greater (after) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see greaterThan()
- *
- * @return bool
- */
- public function gt($date): bool
- {
- return $this->greaterThan($date);
- }
-
- /**
- * Determines if the instance is greater (after) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function greaterThan($date): bool
- {
- return $this > $date;
- }
-
- /**
- * Determines if the instance is greater (after) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see greaterThan()
- *
- * @return bool
- */
- public function isAfter($date): bool
- {
- return $this->greaterThan($date);
- }
-
- /**
- * Determines if the instance is greater (after) than or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see greaterThanOrEqualTo()
- *
- * @return bool
- */
- public function gte($date): bool
- {
- return $this->greaterThanOrEqualTo($date);
- }
-
- /**
- * Determines if the instance is greater (after) than or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function greaterThanOrEqualTo($date): bool
- {
- return $this >= $date;
- }
-
- /**
- * Determines if the instance is less (before) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see lessThan()
- *
- * @return bool
- */
- public function lt($date): bool
- {
- return $this->lessThan($date);
- }
-
- /**
- * Determines if the instance is less (before) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function lessThan($date): bool
- {
- return $this < $date;
- }
-
- /**
- * Determines if the instance is less (before) than another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see lessThan()
- *
- * @return bool
- */
- public function isBefore($date): bool
- {
- return $this->lessThan($date);
- }
-
- /**
- * Determines if the instance is less (before) or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see lessThanOrEqualTo()
- *
- * @return bool
- */
- public function lte($date): bool
- {
- return $this->lessThanOrEqualTo($date);
- }
-
- /**
- * Determines if the instance is less (before) or equal to another
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return bool
- */
- public function lessThanOrEqualTo($date): bool
- {
- return $this <= $date;
- }
-
- /**
- * Determines if the instance is between two others
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- * @param bool $equal Indicates if an equal to comparison should be done
- *
- * @return bool
- */
- public function between($date1, $date2, $equal = true): bool
- {
- if ($date1->greaterThan($date2)) {
- $temp = $date1;
- $date1 = $date2;
- $date2 = $temp;
- }
-
- if ($equal) {
- return $this->greaterThanOrEqualTo($date1) && $this->lessThanOrEqualTo($date2);
- }
-
- return $this->greaterThan($date1) && $this->lessThan($date2);
- }
-
- /**
- * Determines if the instance is between two others
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- * @param bool $equal Indicates if an equal to comparison should be done
- *
- * @return bool
- */
- public function isBetween($date1, $date2, $equal = true): bool
- {
- return $this->between($date1, $date2, $equal);
- }
-
- /**
- * Determines if the instance is a weekday.
- *
- * @return bool
- */
- public function isWeekday()
- {
- return !$this->isWeekend();
- }
-
- /**
- * Determines if the instance is a weekend day.
- *
- * @return bool
- */
- public function isWeekend()
- {
- return in_array($this->dayOfWeek, static::$weekendDays);
- }
-
- /**
- * Determines if the instance is yesterday.
- *
- * @return bool
- */
- public function isYesterday()
- {
- return $this->toDateString() === static::yesterday($this->getTimezone())->toDateString();
- }
-
- /**
- * Determines if the instance is today.
- *
- * @return bool
- */
- public function isToday()
- {
- return $this->toDateString() === $this->nowWithSameTz()->toDateString();
- }
-
- /**
- * Determines if the instance is tomorrow.
- *
- * @return bool
- */
- public function isTomorrow()
- {
- return $this->toDateString() === static::tomorrow($this->getTimezone())->toDateString();
- }
-
- /**
- * Determines if the instance is in the future, ie. greater (after) than now.
- *
- * @return bool
- */
- public function isFuture()
- {
- return $this->greaterThan($this->nowWithSameTz());
- }
-
- /**
- * Determines if the instance is in the past, ie. less (before) than now.
- *
- * @return bool
- */
- public function isPast()
- {
- return $this->lessThan($this->nowWithSameTz());
- }
-
- /**
- * Determines if the instance is a leap year.
- *
- * @return bool
- */
- public function isLeapYear()
- {
- return $this->rawFormat('L') === '1';
- }
-
- /**
- * Determines if the instance is a long year
- *
- * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
- *
- * @return bool
- */
- public function isLongYear()
- {
- return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
- }
-
- /**
- * Compares the formatted values of the two dates.
- *
- * @param string $format date formats to compare.
- * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day.
- *
- * @throws \InvalidArgumentException
- *
- * @return bool
- */
- public function isSameAs($format, $date = null)
- {
- /** @var DateTimeInterface $date */
- $date = $date ?: static::now($this->tz);
-
- static::expectDateTime($date, 'null');
-
- /* @var CarbonInterface $this */
- return $this->rawFormat($format) === ($date instanceof self ? $date->rawFormat($format) : $date->format($format));
- }
-
- /**
- * Determines if the instance is in the current unit given.
- *
- * @param string $unit singular unit string
- * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day.
- *
- * @throws \InvalidArgumentException
- *
- * @return bool
- */
- public function isSameUnit($unit, $date = null)
- {
- $units = [
- // @call isSameUnit
- 'year' => 'Y',
- // @call isSameUnit
- 'week' => 'o-W',
- // @call isSameUnit
- 'day' => 'Y-m-d',
- // @call isSameUnit
- 'hour' => 'Y-m-d H',
- // @call isSameUnit
- 'minute' => 'Y-m-d H:i',
- // @call isSameUnit
- 'second' => 'Y-m-d H:i:s',
- // @call isSameUnit
- 'micro' => 'Y-m-d H:i:s.u',
- // @call isSameUnit
- 'microsecond' => 'Y-m-d H:i:s.u',
- ];
-
- if (!isset($units[$unit])) {
- if (isset($this->$unit)) {
- $date = $date ? static::instance($date) : static::now($this->tz);
-
- static::expectDateTime($date);
-
- return $this->$unit === $date->$unit;
- }
-
- if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
- throw new InvalidArgumentException("Bad comparison unit: '$unit'");
- }
-
- return false;
- }
-
- return $this->isSameAs($units[$unit], $date);
- }
-
- /**
- * Determines if the instance is in the current unit given.
- *
- * @param string $unit The unit to test.
- *
- * @throws \BadMethodCallException
- *
- * @return bool
- */
- public function isCurrentUnit($unit)
- {
- return $this->{'isSame'.ucfirst($unit)}();
- }
-
- /**
- * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
- * @param bool $ofSameYear Check if it is the same month in the same year.
- *
- * @return bool
- */
- public function isSameQuarter($date = null, $ofSameYear = true)
- {
- $date = $date ? static::instance($date) : static::now($this->tz);
-
- static::expectDateTime($date, 'null');
-
- return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date));
- }
-
- /**
- * Checks if the passed in date is in the same month as the instance´s month.
- *
- * Note that this defaults to only comparing the month while ignoring the year.
- * To test if it is the same exact month of the same year, pass in true as the second parameter.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
- * @param bool $ofSameYear Check if it is the same month in the same year.
- *
- * @return bool
- */
- public function isSameMonth($date = null, $ofSameYear = true)
- {
- return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date);
- }
-
- /**
- * Checks if this day is a specific day of the week.
- *
- * @param int $dayOfWeek
- *
- * @return bool
- */
- public function isDayOfWeek($dayOfWeek)
- {
- if (is_string($dayOfWeek) && defined($constant = static::class.'::'.strtoupper($dayOfWeek))) {
- $dayOfWeek = constant($constant);
- }
-
- return $this->dayOfWeek === $dayOfWeek;
- }
-
- /**
- * Check if its the birthday. Compares the date/month values of the two dates.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
- *
- * @return bool
- */
- public function isBirthday($date = null)
- {
- return $this->isSameAs('md', $date);
- }
-
- /**
- * Check if today is the last day of the Month
- *
- * @return bool
- */
- public function isLastOfMonth()
- {
- return $this->day === $this->daysInMonth;
- }
-
- /**
- * Check if the instance is start of day / midnight.
- *
- * @param bool $checkMicroseconds check time at microseconds precision
- *
- * @return bool
- */
- public function isStartOfDay($checkMicroseconds = false)
- {
- /* @var CarbonInterface $this */
- return $checkMicroseconds
- ? $this->rawFormat('H:i:s.u') === '00:00:00.000000'
- : $this->rawFormat('H:i:s') === '00:00:00';
- }
-
- /**
- * Check if the instance is end of day.
- *
- * @param bool $checkMicroseconds check time at microseconds precision
- *
- * @return bool
- */
- public function isEndOfDay($checkMicroseconds = false)
- {
- /* @var CarbonInterface $this */
- return $checkMicroseconds
- ? $this->rawFormat('H:i:s.u') === '23:59:59.999999'
- : $this->rawFormat('H:i:s') === '23:59:59';
- }
-
- /**
- * Check if the instance is start of day / midnight.
- *
- * @return bool
- */
- public function isMidnight()
- {
- return $this->isStartOfDay();
- }
-
- /**
- * Check if the instance is midday.
- *
- * @return bool
- */
- public function isMidday()
- {
- /* @var CarbonInterface $this */
- return $this->rawFormat('G:i:s') === static::$midDayAt.':00:00';
- }
-
- /**
- * Checks if the (date)time string is in a given format.
- *
- * @param string $date
- * @param string $format
- *
- * @return bool
- */
- public static function hasFormat($date, $format)
- {
- try {
- // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string
- // doesn't match the format in any way.
- static::rawCreateFromFormat($format, $date);
-
- // createFromFormat() is known to handle edge cases silently.
- // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format.
- // To ensure we're really testing against our desired format, perform an additional regex validation.
-
- // Preg quote, but remove escaped backslashes since we'll deal with escaped characters in the format string.
- $quotedFormat = str_replace('\\\\', '\\',
- preg_quote($format, '/'));
-
- // Build the regex string
- $regex = '';
- for ($i = 0; $i < strlen($quotedFormat); ++$i) {
- // Backslash – the next character does not represent a date token so add it on as-is and continue.
- // We're doing an extra ++$i here to increment the loop by 2.
- if ($quotedFormat[$i] === '\\') {
- $regex .= '\\'.$quotedFormat[++$i];
- continue;
- }
-
- $regex .= strtr($quotedFormat[$i], static::$regexFormats);
- }
-
- return (bool) preg_match('/^'.$regex.'$/', $date);
- } catch (InvalidArgumentException $e) {
- }
-
- return false;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\Carbon;
-use Carbon\CarbonImmutable;
-use Carbon\CarbonInterface;
-use Closure;
-use DateTime;
-
-/**
- * Trait Converter.
- *
- * Change date into different string formats and types and
- * handle the string cast.
- *
- * Depends on the following methods:
- *
- * @method Carbon|CarbonImmutable copy()
- */
-trait Converter
-{
- /**
- * Format to use for __toString method when type juggling occurs.
- *
- * @var string|Closure|null
- */
- protected static $toStringFormat = null;
-
- /**
- * Reset the format used to the default when type juggling a Carbon instance to a string
- *
- * @return void
- */
- public static function resetToStringFormat()
- {
- static::setToStringFormat(null);
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
- * use other method or custom format passed to format() method if you need to dump an other string
- * format.
- *
- * Set the default format used when type juggling a Carbon instance to a string
- *
- * @param string|Closure|null $format
- *
- * @return void
- */
- public static function setToStringFormat($format)
- {
- static::$toStringFormat = $format;
- }
-
- /**
- * @see https://php.net/manual/en/datetime.format.php
- *
- * @param string $format
- *
- * @return string
- */
- public function format($format)
- {
- $function = $this->localFormatFunction ?: static::$formatFunction;
-
- if (!$function) {
- return $this->rawFormat($format);
- }
-
- if (is_string($function) && method_exists($this, $function)) {
- $function = [$this, $function];
- }
-
- return $function(...func_get_args());
- }
-
- /**
- * @see https://php.net/manual/en/datetime.format.php
- *
- * @param string $format
- *
- * @return string
- */
- public function rawFormat($format)
- {
- return parent::format($format);
- }
-
- /**
- * Format the instance as a string using the set format
- *
- * @example
- * ```
- * echo Carbon::now(); // Carbon instances can be casted to string
- * ```
- *
- * @return string
- */
- public function __toString()
- {
- $format = $this->localToStringFormat ?? static::$toStringFormat;
-
- return $format instanceof Closure
- ? $format($this)
- : $this->rawFormat($format ?: (
- defined('static::DEFAULT_TO_STRING_FORMAT')
- ? static::DEFAULT_TO_STRING_FORMAT
- : CarbonInterface::DEFAULT_TO_STRING_FORMAT
- ));
- }
-
- /**
- * Format the instance as date
- *
- * @example
- * ```
- * echo Carbon::now()->toDateString();
- * ```
- *
- * @return string
- */
- public function toDateString()
- {
- return $this->rawFormat('Y-m-d');
- }
-
- /**
- * Format the instance as a readable date
- *
- * @example
- * ```
- * echo Carbon::now()->toFormattedDateString();
- * ```
- *
- * @return string
- */
- public function toFormattedDateString()
- {
- return $this->rawFormat('M j, Y');
- }
-
- /**
- * Format the instance as time
- *
- * @example
- * ```
- * echo Carbon::now()->toTimeString();
- * ```
- *
- * @return string
- */
- public function toTimeString()
- {
- return $this->rawFormat('H:i:s');
- }
-
- /**
- * Format the instance as date and time
- *
- * @example
- * ```
- * echo Carbon::now()->toDateTimeString();
- * ```
- *
- * @return string
- */
- public function toDateTimeString()
- {
- return $this->rawFormat('Y-m-d H:i:s');
- }
-
- /**
- * Format the instance as date and time T-separated with no timezone
- *
- * @example
- * ```
- * echo Carbon::now()->toDateTimeLocalString();
- * ```
- *
- * @return string
- */
- public function toDateTimeLocalString()
- {
- return $this->rawFormat('Y-m-d\TH:i:s');
- }
-
- /**
- * Format the instance with day, date and time
- *
- * @example
- * ```
- * echo Carbon::now()->toDayDateTimeString();
- * ```
- *
- * @return string
- */
- public function toDayDateTimeString()
- {
- return $this->rawFormat('D, M j, Y g:i A');
- }
-
- /**
- * Format the instance as ATOM
- *
- * @example
- * ```
- * echo Carbon::now()->toAtomString();
- * ```
- *
- * @return string
- */
- public function toAtomString()
- {
- return $this->rawFormat(DateTime::ATOM);
- }
-
- /**
- * Format the instance as COOKIE
- *
- * @example
- * ```
- * echo Carbon::now()->toCookieString();
- * ```
- *
- * @return string
- */
- public function toCookieString()
- {
- return $this->rawFormat(DateTime::COOKIE);
- }
-
- /**
- * Format the instance as ISO8601
- *
- * @example
- * ```
- * echo Carbon::now()->toIso8601String();
- * ```
- *
- * @return string
- */
- public function toIso8601String()
- {
- return $this->toAtomString();
- }
-
- /**
- * Format the instance as RFC822
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc822String();
- * ```
- *
- * @return string
- */
- public function toRfc822String()
- {
- return $this->rawFormat(DateTime::RFC822);
- }
-
- /**
- * Convert the instance to UTC and return as Zulu ISO8601
- *
- * @example
- * ```
- * echo Carbon::now()->toIso8601ZuluString();
- * ```
- *
- * @return string
- */
- public function toIso8601ZuluString()
- {
- return $this->copy()->utc()->rawFormat('Y-m-d\TH:i:s\Z');
- }
-
- /**
- * Format the instance as RFC850
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc850String();
- * ```
- *
- * @return string
- */
- public function toRfc850String()
- {
- return $this->rawFormat(DateTime::RFC850);
- }
-
- /**
- * Format the instance as RFC1036
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc1036String();
- * ```
- *
- * @return string
- */
- public function toRfc1036String()
- {
- return $this->rawFormat(DateTime::RFC1036);
- }
-
- /**
- * Format the instance as RFC1123
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc1123String();
- * ```
- *
- * @return string
- */
- public function toRfc1123String()
- {
- return $this->rawFormat(DateTime::RFC1123);
- }
-
- /**
- * Format the instance as RFC2822
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc2822String();
- * ```
- *
- * @return string
- */
- public function toRfc2822String()
- {
- return $this->rawFormat(DateTime::RFC2822);
- }
-
- /**
- * Format the instance as RFC3339
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc3339String();
- * ```
- *
- * @return string
- */
- public function toRfc3339String()
- {
- return $this->rawFormat(DateTime::RFC3339);
- }
-
- /**
- * Format the instance as RSS
- *
- * @example
- * ```
- * echo Carbon::now()->toRssString();
- * ```
- *
- * @return string
- */
- public function toRssString()
- {
- return $this->rawFormat(DateTime::RSS);
- }
-
- /**
- * Format the instance as W3C
- *
- * @example
- * ```
- * echo Carbon::now()->toW3cString();
- * ```
- *
- * @return string
- */
- public function toW3cString()
- {
- return $this->rawFormat(DateTime::W3C);
- }
-
- /**
- * Format the instance as RFC7231
- *
- * @example
- * ```
- * echo Carbon::now()->toRfc7231String();
- * ```
- *
- * @return string
- */
- public function toRfc7231String()
- {
- return $this->copy()
- ->setTimezone('GMT')
- ->rawFormat(defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT);
- }
-
- /**
- * Get default array representation.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toArray());
- * ```
- *
- * @return array
- */
- public function toArray()
- {
- return [
- 'year' => $this->year,
- 'month' => $this->month,
- 'day' => $this->day,
- 'dayOfWeek' => $this->dayOfWeek,
- 'dayOfYear' => $this->dayOfYear,
- 'hour' => $this->hour,
- 'minute' => $this->minute,
- 'second' => $this->second,
- 'micro' => $this->micro,
- 'timestamp' => $this->timestamp,
- 'formatted' => $this->rawFormat(defined('static::DEFAULT_TO_STRING_FORMAT') ? static::DEFAULT_TO_STRING_FORMAT : CarbonInterface::DEFAULT_TO_STRING_FORMAT),
- 'timezone' => $this->timezone,
- ];
- }
-
- /**
- * Get default object representation.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toObject());
- * ```
- *
- * @return object
- */
- public function toObject()
- {
- return (object) $this->toArray();
- }
-
- /**
- * Returns english human readable complete date string.
- *
- * @example
- * ```
- * echo Carbon::now()->toString();
- * ```
- *
- * @return string
- */
- public function toString()
- {
- return $this->copy()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
- }
-
- /**
- * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
- * 1977-04-22T01:00:00-05:00).
- *
- * @example
- * ```
- * echo Carbon::now('America/Toronto')->toISOString() . "\n";
- * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
- * ```
- *
- * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
- *
- * @return null|string
- */
- public function toISOString($keepOffset = false)
- {
- if (!$this->isValid()) {
- return null;
- }
-
- $keepOffset = (bool) $keepOffset;
- $yearFormat = true ? 'YYYY' : 'YYYYYY';
- $tzFormat = $keepOffset ? 'Z' : '[Z]';
- $date = $keepOffset ? $this : $this->copy()->utc();
-
- return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$tzFormat");
- }
-
- /**
- * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
- *
- * @example
- * ```
- * echo Carbon::now('America/Toronto')->toJSON();
- * ```
- *
- * @return null|string
- */
- public function toJSON()
- {
- return $this->toISOString();
- }
-
- /**
- * Return native DateTime PHP object matching the current instance.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toDateTime());
- * ```
- *
- * @return DateTime
- */
- public function toDateTime()
- {
- return new DateTime($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
- }
-
- /**
- * @alias toDateTime
- *
- * Return native DateTime PHP object matching the current instance.
- *
- * @example
- * ```
- * var_dump(Carbon::now()->toDate());
- * ```
- *
- * @return DateTime
- */
- public function toDate()
- {
- return $this->toDateTime();
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\Carbon;
-use Carbon\CarbonImmutable;
-use Carbon\CarbonInterface;
-use Carbon\CarbonTimeZone;
-use Carbon\Exceptions\InvalidDateException;
-use Carbon\Translator;
-use DateTimeInterface;
-use InvalidArgumentException;
-
-/**
- * Trait Creator.
- *
- * Static creators.
- *
- * Depends on the following methods:
- *
- * @method static Carbon|CarbonImmutable getTestNow()
- */
-trait Creator
-{
- /**
- * The errors that can occur.
- *
- * @var array
- */
- protected static $lastErrors;
-
- /**
- * Create a new Carbon instance.
- *
- * Please see the testing aids section (specifically static::setTestNow())
- * for more on the possibility of this constructor returning a test instance.
- *
- * @param string|null $time
- * @param \DateTimeZone|string|null $tz
- */
- public function __construct($time = null, $tz = null)
- {
- if (is_int($time)) {
- $time = "@$time";
- }
-
- $originalTz = $tz;
-
- // If the class has a test now set and we are trying to create a now()
- // instance then override as required
- $isNow = empty($time) || $time === 'now';
-
- if (method_exists(static::class, 'hasTestNow') &&
- method_exists(static::class, 'getTestNow') &&
- static::hasTestNow() &&
- ($isNow || static::hasRelativeKeywords($time))
- ) {
- static::mockConstructorParameters($time, $tz);
- }
-
- /** @var CarbonTimeZone $timezone */
- $timezone = $this->autoDetectTimeZone($tz, $originalTz);
-
- // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
- if (strpos((string) .1, '.') === false) {
- $locale = setlocale(LC_NUMERIC, '0');
- setlocale(LC_NUMERIC, 'C');
- }
-
- parent::__construct($time ?: 'now', $timezone);
-
- if (isset($locale)) {
- setlocale(LC_NUMERIC, $locale);
- }
-
- static::setLastErrors(parent::getLastErrors());
- }
-
- /**
- * Create a Carbon instance from a DateTime one.
- *
- * @param \DateTimeInterface $date
- *
- * @return static|CarbonInterface
- */
- public static function instance($date)
- {
- if ($date instanceof static) {
- return clone $date;
- }
-
- static::expectDateTime($date);
-
- $instance = new static($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
-
- if ($date instanceof CarbonInterface || $date instanceof Options) {
- $instance->settings($date->getSettings());
- }
-
- return $instance;
- }
-
- /**
- * Create a carbon instance from a string.
- *
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- *
- * @param string|null $time
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function rawParse($time = null, $tz = null)
- {
- if ($time instanceof DateTimeInterface) {
- return static::instance($time);
- }
-
- return new static($time, $tz);
- }
-
- /**
- * Create a carbon instance from a string.
- *
- * This is an alias for the constructor that allows better fluent syntax
- * as it allows you to do Carbon::parse('Monday next week')->fn() rather
- * than (new Carbon('Monday next week'))->fn().
- *
- * @param string|null $time
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function parse($time = null, $tz = null)
- {
- $function = static::$parseFunction;
-
- if (!$function) {
- return static::rawParse($time, $tz);
- }
-
- if (is_string($function) && method_exists(static::class, $function)) {
- $function = [static::class, $function];
- }
-
- return $function(...func_get_args());
- }
-
- /**
- * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
- *
- * @param string $time
- * @param string $locale
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function parseFromLocale($time, $locale, $tz = null)
- {
- return static::rawParse(static::translateTimeString($time, $locale, 'en'), $tz);
- }
-
- /**
- * Get a Carbon instance for the current date and time.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function now($tz = null)
- {
- return new static(null, $tz);
- }
-
- /**
- * Create a Carbon instance for today.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function today($tz = null)
- {
- return static::rawParse('today', $tz);
- }
-
- /**
- * Create a Carbon instance for tomorrow.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function tomorrow($tz = null)
- {
- return static::rawParse('tomorrow', $tz);
- }
-
- /**
- * Create a Carbon instance for yesterday.
- *
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function yesterday($tz = null)
- {
- return static::rawParse('yesterday', $tz);
- }
-
- /**
- * Create a Carbon instance for the greatest supported date.
- *
- * @return static|CarbonInterface
- */
- public static function maxValue()
- {
- if (self::$PHPIntSize === 4) {
- // 32 bit
- return static::createFromTimestamp(PHP_INT_MAX); // @codeCoverageIgnore
- }
-
- // 64 bit
- return static::create(9999, 12, 31, 23, 59, 59);
- }
-
- /**
- * Create a Carbon instance for the lowest supported date.
- *
- * @return static|CarbonInterface
- */
- public static function minValue()
- {
- if (self::$PHPIntSize === 4) {
- // 32 bit
- return static::createFromTimestamp(~PHP_INT_MAX); // @codeCoverageIgnore
- }
-
- // 64 bit
- return static::create(1, 1, 1, 0, 0, 0);
- }
-
- private static function assertBetween($unit, $value, $min, $max)
- {
- if (static::isStrictModeEnabled() && ($value < $min || $value > $max)) {
- throw new InvalidArgumentException("$unit must be between $min and $max, $value given");
- }
- }
-
- /**
- * Create a new Carbon instance from a specific date and time.
- *
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- *
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- *
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param int|null $hour
- * @param int|null $minute
- * @param int|null $second
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null)
- {
- if (is_string($year) && !is_numeric($year)) {
- return static::parse($year, $tz);
- }
-
- $defaults = null;
- $getDefault = function ($unit) use ($tz, &$defaults) {
- if ($defaults === null) {
- $now = static::hasTestNow() ? static::getTestNow() : static::now($tz);
-
- $defaults = array_combine([
- 'year',
- 'month',
- 'day',
- 'hour',
- 'minute',
- 'second',
- ], explode('-', $now->rawFormat('Y-n-j-G-i-s.u')));
- }
-
- return $defaults[$unit];
- };
-
- $year = $year === null ? $getDefault('year') : $year;
- $month = $month === null ? $getDefault('month') : $month;
- $day = $day === null ? $getDefault('day') : $day;
- $hour = $hour === null ? $getDefault('hour') : $hour;
- $minute = $minute === null ? $getDefault('minute') : $minute;
- $second = (float) ($second === null ? $getDefault('second') : $second);
-
- self::assertBetween('month', $month, 0, 99);
- self::assertBetween('day', $day, 0, 99);
- self::assertBetween('hour', $hour, 0, 99);
- self::assertBetween('minute', $minute, 0, 99);
- self::assertBetween('second', $second, 0, 99);
-
- $fixYear = null;
-
- if ($year < 0) {
- $fixYear = $year;
- $year = 0;
- } elseif ($year > 9999) {
- $fixYear = $year - 9999;
- $year = 9999;
- }
-
- $second = ($second < 10 ? '0' : '').number_format($second, 6);
- /** @var CarbonImmutable|Carbon $instance */
- $instance = static::rawCreateFromFormat('!Y-n-j G:i:s.u', sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $tz);
-
- if ($fixYear !== null) {
- $instance = $instance->addYears($fixYear);
- }
-
- return $instance;
- }
-
- /**
- * Create a new safe Carbon instance from a specific date and time.
- *
- * If any of $year, $month or $day are set to null their now() values will
- * be used.
- *
- * If $hour is null it will be set to its now() value and the default
- * values for $minute and $second will be their now() values.
- *
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
- *
- * If one of the set values is not valid, an \InvalidArgumentException
- * will be thrown.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param int|null $hour
- * @param int|null $minute
- * @param int|null $second
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \Carbon\Exceptions\InvalidDateException|\InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
- {
- $fields = static::getRangesByUnit();
-
- foreach ($fields as $field => $range) {
- if ($$field !== null && (!is_int($$field) || $$field < $range[0] || $$field > $range[1])) {
- if (static::isStrictModeEnabled()) {
- throw new InvalidDateException($field, $$field);
- }
-
- return false;
- }
- }
-
- $instance = static::create($year, $month, $day, $hour, $minute, $second, $tz);
-
- foreach (array_reverse($fields) as $field => $range) {
- if ($$field !== null && (!is_int($$field) || $$field !== $instance->$field)) {
- if (static::isStrictModeEnabled()) {
- throw new InvalidDateException($field, $$field);
- }
-
- return false;
- }
- }
-
- return $instance;
- }
-
- /**
- * Create a Carbon instance from just a date. The time portion is set to now.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
- {
- return static::create($year, $month, $day, null, null, null, $tz);
- }
-
- /**
- * Create a Carbon instance from just a date. The time portion is set to midnight.
- *
- * @param int|null $year
- * @param int|null $month
- * @param int|null $day
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null)
- {
- return static::create($year, $month, $day, 0, 0, 0, $tz);
- }
-
- /**
- * Create a Carbon instance from just a time. The date portion is set to today.
- *
- * @param int|null $hour
- * @param int|null $minute
- * @param int|null $second
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null)
- {
- return static::create(null, null, null, $hour, $minute, $second, $tz);
- }
-
- /**
- * Create a Carbon instance from a time string. The date portion is set to today.
- *
- * @param string $time
- * @param \DateTimeZone|string|null $tz
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimeString($time, $tz = null)
- {
- return static::today($tz)->setTimeFromTimeString($time);
- }
-
- /**
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $originalTz
- *
- * @return \DateTimeInterface|false
- */
- private static function createFromFormatAndTimezone($format, $time, $originalTz)
- {
- // Work-around for https://bugs.php.net/bug.php?id=75577
- // @codeCoverageIgnoreStart
- if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
- $format = str_replace('.v', '.u', $format);
- }
- // @codeCoverageIgnoreEnd
-
- if ($originalTz === null) {
- return parent::createFromFormat($format, "$time");
- }
-
- $tz = is_int($originalTz)
- ? @timezone_name_from_abbr('', (int) ($originalTz * 3600), 1)
- : $originalTz;
-
- $tz = static::safeCreateDateTimeZone($tz, $originalTz);
-
- if ($tz === false) {
- return false;
- }
-
- return parent::createFromFormat($format, "$time", $tz);
- }
-
- /**
- * Create a Carbon instance from a specific format.
- *
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function rawCreateFromFormat($format, $time, $tz = null)
- {
- if (preg_match('/(?<!\\\\)(?:\\\\{2})*(a|A)/', $format, $aMatches, PREG_OFFSET_CAPTURE) &&
- preg_match('/(?<!\\\\)(?:\\\\{2})*(h|g|H|G)/', $format, $hMatches, PREG_OFFSET_CAPTURE) &&
- $aMatches[1][1] < $hMatches[1][1] &&
- preg_match('/(am|pm|AM|PM)/', $time)
- ) {
- $format = preg_replace('/^(.*)(?<!\\\\)((?:\\\\{2})*)(a|A)(.*)$/U', '$1$2$4 $3', $format);
- $time = preg_replace('/^(.*)(am|pm|AM|PM)(.*)$/U', '$1$3 $2', $time);
- }
-
- // First attempt to create an instance, so that error messages are based on the unmodified format.
- $date = self::createFromFormatAndTimezone($format, $time, $tz);
- $lastErrors = parent::getLastErrors();
-
- if (($mock = static::getTestNow()) && $date instanceof DateTimeInterface) {
- // Set timezone from mock if custom timezone was neither given directly nor as a part of format.
- // First let's skip the part that will be ignored by the parser.
- $nonEscaped = '(?<!\\\\)(\\\\{2})*';
-
- $nonIgnored = preg_replace("/^.*{$nonEscaped}!/s", '', $format);
-
- if ($tz === null && !preg_match("/{$nonEscaped}[eOPT]/", $nonIgnored)) {
- $tz = $mock->getTimezone();
- }
-
- // Set microseconds to zero to match behavior of DateTime::createFromFormat()
- // See https://bugs.php.net/bug.php?id=74332
- $mock = $mock->copy()->microsecond(0);
-
- // Prepend mock datetime only if the format does not contain non escaped unix epoch reset flag.
- if (!preg_match("/{$nonEscaped}[!|]/", $format)) {
- $format = static::MOCK_DATETIME_FORMAT.' '.$format;
- $time = ($mock instanceof self ? $mock->rawFormat(static::MOCK_DATETIME_FORMAT) : $mock->format(static::MOCK_DATETIME_FORMAT)).' '.$time;
- }
-
- // Regenerate date from the modified format to base result on the mocked instance instead of now.
- $date = self::createFromFormatAndTimezone($format, $time, $tz);
- }
-
- if ($date instanceof DateTimeInterface) {
- $instance = static::instance($date);
- $instance::setLastErrors($lastErrors);
-
- return $instance;
- }
-
- if (static::isStrictModeEnabled()) {
- throw new InvalidArgumentException(implode(PHP_EOL, $lastErrors['errors']));
- }
-
- return false;
- }
-
- /**
- * Create a Carbon instance from a specific format.
- *
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromFormat($format, $time, $tz = null)
- {
- $function = static::$createFromFormatFunction;
-
- if (!$function) {
- return static::rawCreateFromFormat($format, $time, $tz);
- }
-
- if (is_string($function) && method_exists(static::class, $function)) {
- $function = [static::class, $function];
- }
-
- return $function(...func_get_args());
- }
-
- /**
- * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
- *
- * @param string $format Datetime format
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz optional timezone
- * @param string|null $locale locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use)
- * @param \Symfony\Component\Translation\TranslatorInterface $translator optional custom translator to use for macro-formats
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null)
- {
- $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*(LTS|LT|[Ll]{1,4})/', function ($match) use ($locale, $translator) {
- [$code] = $match;
-
- static $formats = null;
-
- if ($formats === null) {
- $translator = $translator ?: Translator::get($locale);
-
- $formats = [
- 'LT' => static::getTranslationMessageWith($translator, 'formats.LT', $locale, 'h:mm A'),
- 'LTS' => static::getTranslationMessageWith($translator, 'formats.LTS', $locale, 'h:mm:ss A'),
- 'L' => static::getTranslationMessageWith($translator, 'formats.L', $locale, 'MM/DD/YYYY'),
- 'LL' => static::getTranslationMessageWith($translator, 'formats.LL', $locale, 'MMMM D, YYYY'),
- 'LLL' => static::getTranslationMessageWith($translator, 'formats.LLL', $locale, 'MMMM D, YYYY h:mm A'),
- 'LLLL' => static::getTranslationMessageWith($translator, 'formats.LLLL', $locale, 'dddd, MMMM D, YYYY h:mm A'),
- ];
- }
-
- return $formats[$code] ?? preg_replace_callback(
- '/MMMM|MM|DD|dddd/',
- function ($code) {
- return mb_substr($code[0], 1);
- },
- $formats[strtoupper($code)] ?? ''
- );
- }, $format);
-
- $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*('.CarbonInterface::ISO_FORMAT_REGEXP.'|[A-Za-z])/', function ($match) {
- [$code] = $match;
-
- static $replacements = null;
-
- if ($replacements === null) {
- $replacements = [
- 'OD' => 'd',
- 'OM' => 'M',
- 'OY' => 'Y',
- 'OH' => 'G',
- 'Oh' => 'g',
- 'Om' => 'i',
- 'Os' => 's',
- 'D' => 'd',
- 'DD' => 'd',
- 'Do' => 'd',
- 'd' => '!',
- 'dd' => '!',
- 'ddd' => 'D',
- 'dddd' => 'D',
- 'DDD' => 'z',
- 'DDDD' => 'z',
- 'DDDo' => 'z',
- 'e' => '!',
- 'E' => '!',
- 'H' => 'G',
- 'HH' => 'H',
- 'h' => 'g',
- 'hh' => 'h',
- 'k' => 'G',
- 'kk' => 'G',
- 'hmm' => 'gi',
- 'hmmss' => 'gis',
- 'Hmm' => 'Gi',
- 'Hmmss' => 'Gis',
- 'm' => 'i',
- 'mm' => 'i',
- 'a' => 'a',
- 'A' => 'a',
- 's' => 's',
- 'ss' => 's',
- 'S' => '*',
- 'SS' => '*',
- 'SSS' => '*',
- 'SSSS' => '*',
- 'SSSSS' => '*',
- 'SSSSSS' => 'u',
- 'SSSSSSS' => 'u*',
- 'SSSSSSSS' => 'u*',
- 'SSSSSSSSS' => 'u*',
- 'M' => 'm',
- 'MM' => 'm',
- 'MMM' => 'M',
- 'MMMM' => 'M',
- 'Mo' => 'm',
- 'Q' => '!',
- 'Qo' => '!',
- 'G' => '!',
- 'GG' => '!',
- 'GGG' => '!',
- 'GGGG' => '!',
- 'GGGGG' => '!',
- 'g' => '!',
- 'gg' => '!',
- 'ggg' => '!',
- 'gggg' => '!',
- 'ggggg' => '!',
- 'W' => '!',
- 'WW' => '!',
- 'Wo' => '!',
- 'w' => '!',
- 'ww' => '!',
- 'wo' => '!',
- 'x' => 'U???',
- 'X' => 'U',
- 'Y' => 'Y',
- 'YY' => 'y',
- 'YYYY' => 'Y',
- 'YYYYY' => 'Y',
- 'YYYYYY' => 'Y',
- 'z' => 'e',
- 'zz' => 'e',
- 'Z' => 'e',
- 'ZZ' => 'e',
- ];
- }
-
- $format = $replacements[$code] ?? '?';
-
- if ($format === '!') {
- throw new InvalidArgumentException("Format $code not supported for creation.");
- }
-
- return $format;
- }, $format);
-
- return static::rawCreateFromFormat($format, $time, $tz);
- }
-
- /**
- * Create a Carbon instance from a specific format and a string in a given language.
- *
- * @param string $format Datetime format
- * @param string $locale
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromLocaleFormat($format, $locale, $time, $tz = null)
- {
- return static::rawCreateFromFormat($format, static::translateTimeString($time, $locale, 'en'), $tz);
- }
-
- /**
- * Create a Carbon instance from a specific ISO format and a string in a given language.
- *
- * @param string $format Datetime ISO format
- * @param string $locale
- * @param string $time
- * @param \DateTimeZone|string|false|null $tz
- *
- * @throws InvalidArgumentException
- *
- * @return static|CarbonInterface|false
- */
- public static function createFromLocaleIsoFormat($format, $locale, $time, $tz = null)
- {
- $time = static::translateTimeString($time, $locale, 'en', CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS | CarbonInterface::TRANSLATE_MERIDIEM);
-
- return static::createFromIsoFormat($format, $time, $tz, $locale);
- }
-
- /**
- * Make a Carbon instance from given variable if possible.
- *
- * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
- * and recurrences). Throw an exception for invalid format, but otherwise return null.
- *
- * @param mixed $var
- *
- * @return static|CarbonInterface|null
- */
- public static function make($var)
- {
- if ($var instanceof DateTimeInterface) {
- return static::instance($var);
- }
-
- $date = null;
-
- if (is_string($var)) {
- $var = trim($var);
- $first = substr($var, 0, 1);
-
- if (is_string($var) && $first !== 'P' && $first !== 'R' && preg_match('/[a-z0-9]/i', $var)) {
- $date = static::parse($var);
- }
- }
-
- return $date;
- }
-
- /**
- * Set last errors.
- *
- * @param array $lastErrors
- *
- * @return void
- */
- private static function setLastErrors(array $lastErrors)
- {
- static::$lastErrors = $lastErrors;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function getLastErrors()
- {
- return static::$lastErrors;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use BadMethodCallException;
-use Carbon\CarbonInterface;
-use Carbon\CarbonTimeZone;
-use Closure;
-use DateTime;
-use DateTimeInterface;
-use InvalidArgumentException;
-use ReflectionException;
-
-/**
- * A simple API extension for DateTime.
- *
- * <autodoc generated by `composer phpdoc`>
- *
- * @property int $year
- * @property int $yearIso
- * @property int $month
- * @property int $day
- * @property int $hour
- * @property int $minute
- * @property int $second
- * @property int $micro
- * @property int $microsecond
- * @property int $timestamp seconds since the Unix Epoch
- * @property string $englishDayOfWeek the day of week in English
- * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
- * @property string $englishMonth the month in English
- * @property string $shortEnglishMonth the abbreviated month in English
- * @property string $localeDayOfWeek the day of week in current locale LC_TIME
- * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
- * @property string $localeMonth the month in current locale LC_TIME
- * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
- * @property int $milliseconds
- * @property int $millisecond
- * @property int $milli
- * @property int $week 1 through 53
- * @property int $isoWeek 1 through 53
- * @property int $weekYear year according to week format
- * @property int $isoWeekYear year according to ISO week format
- * @property int $dayOfYear 1 through 366
- * @property int $age does a diffInYears() with default parameters
- * @property int $offset the timezone offset in seconds from UTC
- * @property int $offsetMinutes the timezone offset in minutes from UTC
- * @property int $offsetHours the timezone offset in hours from UTC
- * @property CarbonTimeZone $timezone the current timezone
- * @property CarbonTimeZone $tz alias of $timezone
- * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
- * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
- * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
- * @property-read int $daysInMonth number of days in the given month
- * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
- * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
- * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
- * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- * @property-read int $noZeroHour current hour from 1 to 24
- * @property-read int $weeksInYear 51 through 53
- * @property-read int $isoWeeksInYear 51 through 53
- * @property-read int $weekOfMonth 1 through 5
- * @property-read int $weekNumberInMonth 1 through 5
- * @property-read int $firstWeekDay 0 through 6
- * @property-read int $lastWeekDay 0 through 6
- * @property-read int $daysInYear 365 or 366
- * @property-read int $quarter the quarter of this instance, 1 - 4
- * @property-read int $decade the decade of this instance
- * @property-read int $century the century of this instance
- * @property-read int $millennium the millennium of this instance
- * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
- * @property-read bool $local checks if the timezone is local, true if local, false otherwise
- * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
- * @property-read string $timezoneName the current timezone name
- * @property-read string $tzName alias of $timezoneName
- * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
- * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
- * @property-read string $locale locale of the current instance
- *
- * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
- * @method bool isLocal() Check if the current instance has non-UTC timezone.
- * @method bool isValid() Check if the current instance is a valid date.
- * @method bool isDST() Check if the current instance is in a daylight saving time.
- * @method bool isSunday() Checks if the instance day is sunday.
- * @method bool isMonday() Checks if the instance day is monday.
- * @method bool isTuesday() Checks if the instance day is tuesday.
- * @method bool isWednesday() Checks if the instance day is wednesday.
- * @method bool isThursday() Checks if the instance day is thursday.
- * @method bool isFriday() Checks if the instance day is friday.
- * @method bool isSaturday() Checks if the instance day is saturday.
- * @method bool isSameYear(\DateTimeInterface $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
- * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
- * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
- * @method bool isSameWeek(\DateTimeInterface $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
- * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
- * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
- * @method bool isSameDay(\DateTimeInterface $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
- * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
- * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
- * @method bool isSameHour(\DateTimeInterface $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
- * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
- * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
- * @method bool isSameMinute(\DateTimeInterface $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
- * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
- * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
- * @method bool isSameSecond(\DateTimeInterface $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
- * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
- * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
- * @method bool isSameMicro(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isSameMicrosecond(\DateTimeInterface $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
- * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
- * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
- * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
- * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
- * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
- * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
- * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
- * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
- * @method bool isSameDecade(\DateTimeInterface $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
- * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
- * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
- * @method bool isSameCentury(\DateTimeInterface $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
- * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
- * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
- * @method bool isSameMillennium(\DateTimeInterface $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
- * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
- * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
- * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
- * @method $this years(int $value) Set current instance year to the given value.
- * @method $this year(int $value) Set current instance year to the given value.
- * @method $this setYears(int $value) Set current instance year to the given value.
- * @method $this setYear(int $value) Set current instance year to the given value.
- * @method $this months(int $value) Set current instance month to the given value.
- * @method $this month(int $value) Set current instance month to the given value.
- * @method $this setMonths(int $value) Set current instance month to the given value.
- * @method $this setMonth(int $value) Set current instance month to the given value.
- * @method $this days(int $value) Set current instance day to the given value.
- * @method $this day(int $value) Set current instance day to the given value.
- * @method $this setDays(int $value) Set current instance day to the given value.
- * @method $this setDay(int $value) Set current instance day to the given value.
- * @method $this hours(int $value) Set current instance hour to the given value.
- * @method $this hour(int $value) Set current instance hour to the given value.
- * @method $this setHours(int $value) Set current instance hour to the given value.
- * @method $this setHour(int $value) Set current instance hour to the given value.
- * @method $this minutes(int $value) Set current instance minute to the given value.
- * @method $this minute(int $value) Set current instance minute to the given value.
- * @method $this setMinutes(int $value) Set current instance minute to the given value.
- * @method $this setMinute(int $value) Set current instance minute to the given value.
- * @method $this seconds(int $value) Set current instance second to the given value.
- * @method $this second(int $value) Set current instance second to the given value.
- * @method $this setSeconds(int $value) Set current instance second to the given value.
- * @method $this setSecond(int $value) Set current instance second to the given value.
- * @method $this millis(int $value) Set current instance millisecond to the given value.
- * @method $this milli(int $value) Set current instance millisecond to the given value.
- * @method $this setMillis(int $value) Set current instance millisecond to the given value.
- * @method $this setMilli(int $value) Set current instance millisecond to the given value.
- * @method $this milliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this millisecond(int $value) Set current instance millisecond to the given value.
- * @method $this setMilliseconds(int $value) Set current instance millisecond to the given value.
- * @method $this setMillisecond(int $value) Set current instance millisecond to the given value.
- * @method $this micros(int $value) Set current instance microsecond to the given value.
- * @method $this micro(int $value) Set current instance microsecond to the given value.
- * @method $this setMicros(int $value) Set current instance microsecond to the given value.
- * @method $this setMicro(int $value) Set current instance microsecond to the given value.
- * @method $this microseconds(int $value) Set current instance microsecond to the given value.
- * @method $this microsecond(int $value) Set current instance microsecond to the given value.
- * @method $this setMicroseconds(int $value) Set current instance microsecond to the given value.
- * @method $this setMicrosecond(int $value) Set current instance microsecond to the given value.
- * @method $this addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
- * @method $this addYear() Add one year to the instance (using date interval).
- * @method $this subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
- * @method $this subYear() Sub one year to the instance (using date interval).
- * @method $this addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
- * @method $this addMonth() Add one month to the instance (using date interval).
- * @method $this subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
- * @method $this subMonth() Sub one month to the instance (using date interval).
- * @method $this addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
- * @method $this addDay() Add one day to the instance (using date interval).
- * @method $this subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
- * @method $this subDay() Sub one day to the instance (using date interval).
- * @method $this addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
- * @method $this addHour() Add one hour to the instance (using date interval).
- * @method $this subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
- * @method $this subHour() Sub one hour to the instance (using date interval).
- * @method $this addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
- * @method $this addMinute() Add one minute to the instance (using date interval).
- * @method $this subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
- * @method $this subMinute() Sub one minute to the instance (using date interval).
- * @method $this addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
- * @method $this addSecond() Add one second to the instance (using date interval).
- * @method $this subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
- * @method $this subSecond() Sub one second to the instance (using date interval).
- * @method $this addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMilli() Add one millisecond to the instance (using date interval).
- * @method $this subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMilli() Sub one millisecond to the instance (using date interval).
- * @method $this addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMillisecond() Add one millisecond to the instance (using date interval).
- * @method $this subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMillisecond() Sub one millisecond to the instance (using date interval).
- * @method $this addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicro() Add one microsecond to the instance (using date interval).
- * @method $this subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicro() Sub one microsecond to the instance (using date interval).
- * @method $this addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this addMicrosecond() Add one microsecond to the instance (using date interval).
- * @method $this subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
- * @method $this subMicrosecond() Sub one microsecond to the instance (using date interval).
- * @method $this addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
- * @method $this addMillennium() Add one millennium to the instance (using date interval).
- * @method $this subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
- * @method $this subMillennium() Sub one millennium to the instance (using date interval).
- * @method $this addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
- * @method $this addCentury() Add one century to the instance (using date interval).
- * @method $this subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
- * @method $this subCentury() Sub one century to the instance (using date interval).
- * @method $this addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
- * @method $this addDecade() Add one decade to the instance (using date interval).
- * @method $this subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
- * @method $this subDecade() Sub one decade to the instance (using date interval).
- * @method $this addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
- * @method $this addQuarter() Add one quarter to the instance (using date interval).
- * @method $this subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
- * @method $this subQuarter() Sub one quarter to the instance (using date interval).
- * @method $this addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
- * @method $this subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
- * @method $this addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
- * @method $this addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
- * @method $this addWeek() Add one week to the instance (using date interval).
- * @method $this subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
- * @method $this subWeek() Sub one week to the instance (using date interval).
- * @method $this addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this addWeekday() Add one weekday to the instance (using date interval).
- * @method $this subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
- * @method $this subWeekday() Sub one weekday to the instance (using date interval).
- * @method $this addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicro() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicro() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMicrosecond() Add one microsecond to the instance (using timestamp).
- * @method $this subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
- * @method $this addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMilli() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMilli() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillisecond() Add one millisecond to the instance (using timestamp).
- * @method $this subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillisecond() Sub one millisecond to the instance (using timestamp).
- * @method $this addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealSecond() Add one second to the instance (using timestamp).
- * @method $this subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealSecond() Sub one second to the instance (using timestamp).
- * @method $this addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMinute() Add one minute to the instance (using timestamp).
- * @method $this subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMinute() Sub one minute to the instance (using timestamp).
- * @method $this addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealHour() Add one hour to the instance (using timestamp).
- * @method $this subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealHour() Sub one hour to the instance (using timestamp).
- * @method $this addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDay() Add one day to the instance (using timestamp).
- * @method $this subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDay() Sub one day to the instance (using timestamp).
- * @method $this addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealWeek() Add one week to the instance (using timestamp).
- * @method $this subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealWeek() Sub one week to the instance (using timestamp).
- * @method $this addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMonth() Add one month to the instance (using timestamp).
- * @method $this subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMonth() Sub one month to the instance (using timestamp).
- * @method $this addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealQuarter() Add one quarter to the instance (using timestamp).
- * @method $this subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealQuarter() Sub one quarter to the instance (using timestamp).
- * @method $this addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealYear() Add one year to the instance (using timestamp).
- * @method $this subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealYear() Sub one year to the instance (using timestamp).
- * @method $this addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealDecade() Add one decade to the instance (using timestamp).
- * @method $this subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealDecade() Sub one decade to the instance (using timestamp).
- * @method $this addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealCentury() Add one century to the instance (using timestamp).
- * @method $this subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealCentury() Sub one century to the instance (using timestamp).
- * @method $this addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this addRealMillennium() Add one millennium to the instance (using timestamp).
- * @method $this subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
- * @method $this subRealMillennium() Sub one millennium to the instance (using timestamp).
- * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
- * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
- * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
- * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
- * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
- * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
- * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
- * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
- * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
- * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
- * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
- * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
- * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
- * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
- * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
- * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
- * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
- * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
- * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
- * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
- * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
- * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
- * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
- * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
- * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
- * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
- * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
- * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
- * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
- * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
- * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
- * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
- * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
- * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
- * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
- * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
- * @method string shortAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longAbsoluteDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToNowDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string shortRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- * @method string longRelativeToOtherDiffForHumans(\DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
- *
- * </autodoc>
- */
-trait Date
-{
- use Boundaries;
- use Comparison;
- use Converter;
- use Creator;
- use Difference;
- use Macro;
- use Modifiers;
- use Mutability;
- use Options;
- use Rounding;
- use Serialization;
- use Test;
- use Timestamp;
- use Units;
- use Week;
-
- /**
- * Names of days of the week.
- *
- * @var array
- */
- protected static $days = [
- // @call isDayOfWeek
- self::SUNDAY => 'Sunday',
- // @call isDayOfWeek
- self::MONDAY => 'Monday',
- // @call isDayOfWeek
- self::TUESDAY => 'Tuesday',
- // @call isDayOfWeek
- self::WEDNESDAY => 'Wednesday',
- // @call isDayOfWeek
- self::THURSDAY => 'Thursday',
- // @call isDayOfWeek
- self::FRIDAY => 'Friday',
- // @call isDayOfWeek
- self::SATURDAY => 'Saturday',
- ];
-
- /**
- * Will UTF8 encoding be used to print localized date/time ?
- *
- * @var bool
- */
- protected static $utf8 = false;
-
- /**
- * List of unit and magic methods associated as doc-comments.
- *
- * @var array
- */
- protected static $units = [
- // @call setUnit
- // @call addUnit
- 'year',
- // @call setUnit
- // @call addUnit
- 'month',
- // @call setUnit
- // @call addUnit
- 'day',
- // @call setUnit
- // @call addUnit
- 'hour',
- // @call setUnit
- // @call addUnit
- 'minute',
- // @call setUnit
- // @call addUnit
- 'second',
- // @call setUnit
- // @call addUnit
- 'milli',
- // @call setUnit
- // @call addUnit
- 'millisecond',
- // @call setUnit
- // @call addUnit
- 'micro',
- // @call setUnit
- // @call addUnit
- 'microsecond',
- ];
-
- /**
- * Creates a DateTimeZone from a string, DateTimeZone or integer offset.
- *
- * @param \DateTimeZone|string|int|null $object original value to get CarbonTimeZone from it.
- * @param \DateTimeZone|string|int|null $objectDump dump of the object for error messages.
- *
- * @throws \InvalidArgumentException
- *
- * @return CarbonTimeZone|false
- */
- protected static function safeCreateDateTimeZone($object, $objectDump = null)
- {
- return CarbonTimeZone::instance($object, $objectDump);
- }
-
- /**
- * Creates a DateTimeZone from a string, DateTimeZone or integer offset then convert it as region timezone
- * if integer.
- *
- * @param \DateTimeZone|string|int|null $object
- * @param \DateTimeZone|string|int|null $originalObject if different
- *
- * @throws \InvalidArgumentException
- *
- * @return CarbonTimeZone|false
- */
- protected function autoDetectTimeZone($object, $originalObject = null)
- {
- /** @var CarbonTimeZone $timezone */
- $timezone = CarbonTimeZone::instance($object);
- if ($timezone && is_int($originalObject ?: $object)) {
- $timezone = $timezone->toRegionTimeZone($this);
- }
-
- return $timezone;
- }
-
- /**
- * Get the TimeZone associated with the Carbon instance (as CarbonTimeZone).
- *
- * @return CarbonTimeZone
- *
- * @link http://php.net/manual/en/datetime.gettimezone.php
- */
- public function getTimezone()
- {
- return CarbonTimeZone::instance(parent::getTimezone());
- }
-
- /**
- * List of minimum and maximums for each unit.
- *
- * @return array
- */
- protected static function getRangesByUnit()
- {
- return [
- // @call roundUnit
- 'year' => [1, 9999],
- // @call roundUnit
- 'month' => [1, static::MONTHS_PER_YEAR],
- // @call roundUnit
- 'day' => [1, 31],
- // @call roundUnit
- 'hour' => [0, static::HOURS_PER_DAY - 1],
- // @call roundUnit
- 'minute' => [0, static::MINUTES_PER_HOUR - 1],
- // @call roundUnit
- 'second' => [0, static::SECONDS_PER_MINUTE - 1],
- ];
- }
-
- /**
- * Get a copy of the instance.
- *
- * @return static|CarbonInterface
- */
- public function copy()
- {
- return clone $this;
- }
-
- /**
- * @alias copy
- *
- * Get a copy of the instance.
- *
- * @return static|CarbonInterface
- */
- public function clone()
- {
- return clone $this;
- }
-
- /**
- * Returns a present instance in the same timezone.
- *
- * @return static|CarbonInterface
- */
- public function nowWithSameTz()
- {
- return static::now($this->getTimezone());
- }
-
- /**
- * Throws an exception if the given object is not a DateTime and does not implement DateTimeInterface.
- *
- * @param mixed $date
- * @param string|array $other
- *
- * @throws \InvalidArgumentException
- */
- protected static function expectDateTime($date, $other = [])
- {
- $message = 'Expected ';
- foreach ((array) $other as $expect) {
- $message .= "$expect, ";
- }
-
- if (!$date instanceof DateTime && !$date instanceof DateTimeInterface) {
- throw new InvalidArgumentException(
- $message.'DateTime or DateTimeInterface, '.
- (is_object($date) ? get_class($date) : gettype($date)).' given'
- );
- }
- }
-
- /**
- * Return the Carbon instance passed through, a now instance in the same timezone
- * if null given or parse the input if string given.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
- *
- * @return static|CarbonInterface
- */
- protected function resolveCarbon($date = null)
- {
- if (!$date) {
- return $this->nowWithSameTz();
- }
-
- if (is_string($date)) {
- return static::parse($date, $this->getTimezone());
- }
-
- static::expectDateTime($date, ['null', 'string']);
-
- return $date instanceof self ? $date : static::instance($date);
- }
-
- ///////////////////////////////////////////////////////////////////
- ///////////////////////// GETTERS AND SETTERS /////////////////////
- ///////////////////////////////////////////////////////////////////
-
- /**
- * Get a part of the Carbon object
- *
- * @param string $name
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return string|int|bool|\DateTimeZone|null
- */
- public function __get($name)
- {
- return $this->get($name);
- }
-
- /**
- * Get a part of the Carbon object
- *
- * @param string $name
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return string|int|bool|\DateTimeZone|null
- */
- public function get($name)
- {
- static $formats = [
- // @property int
- 'year' => 'Y',
- // @property int
- 'yearIso' => 'o',
- // @property int
- // @call isSameUnit
- 'month' => 'n',
- // @property int
- 'day' => 'j',
- // @property int
- 'hour' => 'G',
- // @property int
- 'minute' => 'i',
- // @property int
- 'second' => 's',
- // @property int
- 'micro' => 'u',
- // @property int
- 'microsecond' => 'u',
- // @property-read int 0 (for Sunday) through 6 (for Saturday)
- 'dayOfWeek' => 'w',
- // @property-read int 1 (for Monday) through 7 (for Sunday)
- 'dayOfWeekIso' => 'N',
- // @property-read int ISO-8601 week number of year, weeks starting on Monday
- 'weekOfYear' => 'W',
- // @property-read int number of days in the given month
- 'daysInMonth' => 't',
- // @property int seconds since the Unix Epoch
- 'timestamp' => 'U',
- // @property-read string "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
- 'latinMeridiem' => 'a',
- // @property-read string "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
- 'latinUpperMeridiem' => 'A',
- // @property string the day of week in English
- 'englishDayOfWeek' => 'l',
- // @property string the abbreviated day of week in English
- 'shortEnglishDayOfWeek' => 'D',
- // @property string the month in English
- 'englishMonth' => 'F',
- // @property string the abbreviated month in English
- 'shortEnglishMonth' => 'M',
- // @property string the day of week in current locale LC_TIME
- 'localeDayOfWeek' => '%A',
- // @property string the abbreviated day of week in current locale LC_TIME
- 'shortLocaleDayOfWeek' => '%a',
- // @property string the month in current locale LC_TIME
- 'localeMonth' => '%B',
- // @property string the abbreviated month in current locale LC_TIME
- 'shortLocaleMonth' => '%b',
- ];
-
- switch (true) {
- case isset($formats[$name]):
- $format = $formats[$name];
- $method = substr($format, 0, 1) === '%' ? 'formatLocalized' : 'rawFormat';
- $value = $this->$method($format);
-
- return is_numeric($value) ? (int) $value : $value;
-
- // @property-read string long name of weekday translated according to Carbon locale, in english if no translation available for current language
- case $name === 'dayName':
- return $this->getTranslatedDayName();
- // @property-read string short name of weekday translated according to Carbon locale, in english if no translation available for current language
- case $name === 'shortDayName':
- return $this->getTranslatedShortDayName();
- // @property-read string very short name of weekday translated according to Carbon locale, in english if no translation available for current language
- case $name === 'minDayName':
- return $this->getTranslatedMinDayName();
- // @property-read string long name of month translated according to Carbon locale, in english if no translation available for current language
- case $name === 'monthName':
- return $this->getTranslatedMonthName();
- // @property-read string short name of month translated according to Carbon locale, in english if no translation available for current language
- case $name === 'shortMonthName':
- return $this->getTranslatedShortMonthName();
- // @property-read string lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- case $name === 'meridiem':
- return $this->meridiem(true);
- // @property-read string uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
- case $name === 'upperMeridiem':
- return $this->meridiem();
- // @property-read int current hour from 1 to 24
- case $name === 'noZeroHour':
- return $this->hour ?: 24;
- // @property int
- case $name === 'milliseconds':
- // @property int
- case $name === 'millisecond':
- // @property int
- case $name === 'milli':
- return (int) floor($this->rawFormat('u') / 1000);
-
- // @property int 1 through 53
- case $name === 'week':
- return (int) $this->week();
-
- // @property int 1 through 53
- case $name === 'isoWeek':
- return (int) $this->isoWeek();
-
- // @property int year according to week format
- case $name === 'weekYear':
- return (int) $this->weekYear();
-
- // @property int year according to ISO week format
- case $name === 'isoWeekYear':
- return (int) $this->isoWeekYear();
-
- // @property-read int 51 through 53
- case $name === 'weeksInYear':
- return (int) $this->weeksInYear();
-
- // @property-read int 51 through 53
- case $name === 'isoWeeksInYear':
- return (int) $this->isoWeeksInYear();
-
- // @property-read int 1 through 5
- case $name === 'weekOfMonth':
- return (int) ceil($this->day / static::DAYS_PER_WEEK);
-
- // @property-read int 1 through 5
- case $name === 'weekNumberInMonth':
- return (int) ceil(($this->day + $this->copy()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);
-
- // @property-read int 0 through 6
- case $name === 'firstWeekDay':
- return $this->localTranslator ? ($this->getTranslationMessage('first_day_of_week') ?? 0) : static::getWeekStartsAt();
-
- // @property-read int 0 through 6
- case $name === 'lastWeekDay':
- return $this->localTranslator ? (($this->getTranslationMessage('first_day_of_week') ?? 0) + static::DAYS_PER_WEEK - 1) % static::DAYS_PER_WEEK : static::getWeekEndsAt();
-
- // @property int 1 through 366
- case $name === 'dayOfYear':
- return 1 + intval($this->rawFormat('z'));
-
- // @property-read int 365 or 366
- case $name === 'daysInYear':
- return $this->isLeapYear() ? 366 : 365;
-
- // @property int does a diffInYears() with default parameters
- case $name === 'age':
- return $this->diffInYears();
-
- // @property-read int the quarter of this instance, 1 - 4
- // @call isSameUnit
- case $name === 'quarter':
- return (int) ceil($this->month / static::MONTHS_PER_QUARTER);
-
- // @property-read int the decade of this instance
- // @call isSameUnit
- case $name === 'decade':
- return (int) ceil($this->year / static::YEARS_PER_DECADE);
-
- // @property-read int the century of this instance
- // @call isSameUnit
- case $name === 'century':
- $factor = 1;
- $year = $this->year;
- if ($year < 0) {
- $year = -$year;
- $factor = -1;
- }
-
- return (int) ($factor * ceil($year / static::YEARS_PER_CENTURY));
-
- // @property-read int the millennium of this instance
- // @call isSameUnit
- case $name === 'millennium':
- $factor = 1;
- $year = $this->year;
- if ($year < 0) {
- $year = -$year;
- $factor = -1;
- }
-
- return (int) ($factor * ceil($year / static::YEARS_PER_MILLENNIUM));
-
- // @property int the timezone offset in seconds from UTC
- case $name === 'offset':
- return $this->getOffset();
-
- // @property int the timezone offset in minutes from UTC
- case $name === 'offsetMinutes':
- return $this->getOffset() / static::SECONDS_PER_MINUTE;
-
- // @property int the timezone offset in hours from UTC
- case $name === 'offsetHours':
- return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR;
-
- // @property-read bool daylight savings time indicator, true if DST, false otherwise
- case $name === 'dst':
- return $this->rawFormat('I') === '1';
-
- // @property-read bool checks if the timezone is local, true if local, false otherwise
- case $name === 'local':
- return $this->getOffset() === $this->copy()->setTimezone(date_default_timezone_get())->getOffset();
-
- // @property-read bool checks if the timezone is UTC, true if UTC, false otherwise
- case $name === 'utc':
- return $this->getOffset() === 0;
-
- // @property CarbonTimeZone $timezone the current timezone
- // @property CarbonTimeZone $tz alias of $timezone
- case $name === 'timezone' || $name === 'tz':
- return CarbonTimeZone::instance($this->getTimezone());
-
- // @property-read string $timezoneName the current timezone name
- // @property-read string $tzName alias of $timezoneName
- case $name === 'timezoneName' || $name === 'tzName':
- return $this->getTimezone()->getName();
-
- // @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
- // @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
- case $name === 'timezoneAbbreviatedName' || $name === 'tzAbbrName':
- return CarbonTimeZone::instance($this->getTimezone())->getAbbr($this->dst);
-
- // @property-read string locale of the current instance
- case $name === 'locale':
- return $this->getLocalTranslator()->getLocale();
-
- default:
- if (static::hasMacro($macro = 'get'.ucfirst($name))) {
- return $this->$macro();
- }
-
- throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
- }
- }
-
- /**
- * Check if an attribute exists on the object
- *
- * @param string $name
- *
- * @return bool
- */
- public function __isset($name)
- {
- try {
- $this->__get($name);
- } catch (InvalidArgumentException | ReflectionException $e) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Set a part of the Carbon object
- *
- * @param string $name
- * @param string|int|\DateTimeZone $value
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return void
- */
- public function __set($name, $value)
- {
- $this->set($name, $value);
- }
-
- /**
- * Set a part of the Carbon object
- *
- * @param string|array $name
- * @param string|int|\DateTimeZone $value
- *
- * @throws InvalidArgumentException|ReflectionException
- *
- * @return $this
- */
- public function set($name, $value = null)
- {
- if ($this->isImmutable()) {
- throw new \RuntimeException(sprintf(
- '%s class is immutable.', static::class
- ));
- }
-
- if (is_array($name)) {
- foreach ($name as $_name => $value) {
- $this->set($_name, $value);
- }
-
- return $this;
- }
-
- switch ($name) {
- case 'milliseconds':
- case 'millisecond':
- case 'milli':
- case 'microseconds':
- case 'microsecond':
- case 'micro':
- if (substr($name, 0, 5) === 'milli') {
- $value *= 1000;
- }
- while ($value < 0) {
- $this->subSecond();
- $value += static::MICROSECONDS_PER_SECOND;
- }
- while ($value >= static::MICROSECONDS_PER_SECOND) {
- $this->addSecond();
- $value -= static::MICROSECONDS_PER_SECOND;
- }
- $this->modify($this->rawFormat('H:i:s.').str_pad((string) round($value), 6, '0', STR_PAD_LEFT));
- break;
-
- case 'year':
- case 'month':
- case 'day':
- case 'hour':
- case 'minute':
- case 'second':
- [$year, $month, $day, $hour, $minute, $second] = explode('-', $this->rawFormat('Y-n-j-G-i-s'));
- $$name = $value;
- $this->setDateTime($year, $month, $day, $hour, $minute, $second);
- break;
-
- case 'week':
- return $this->week($value);
-
- case 'isoWeek':
- return $this->isoWeek($value);
-
- case 'weekYear':
- return $this->weekYear($value);
-
- case 'isoWeekYear':
- return $this->isoWeekYear($value);
-
- case 'dayOfYear':
- return $this->addDays($value - $this->dayOfYear);
-
- case 'timestamp':
- parent::setTimestamp((int) $value);
- break;
-
- case 'offset':
- $this->setTimezone(static::safeCreateDateTimeZone($value / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR));
- break;
-
- case 'offsetMinutes':
- $this->setTimezone(static::safeCreateDateTimeZone($value / static::MINUTES_PER_HOUR));
- break;
-
- case 'offsetHours':
- $this->setTimezone(static::safeCreateDateTimeZone($value));
- break;
-
- case 'timezone':
- case 'tz':
- $this->setTimezone($value);
- break;
-
- default:
- if (static::hasMacro($macro = 'set'.ucfirst($name))) {
- $this->$macro($value);
-
- break;
- }
-
- if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
- throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
- }
-
- $this->$name = $value;
- }
-
- return $this;
- }
-
- protected function getTranslatedFormByRegExp($baseKey, $keySuffix, $context, $subKey, $defaultValue)
- {
- $key = $baseKey.$keySuffix;
- $standaloneKey = "${key}_standalone";
- $baseTranslation = $this->getTranslationMessage($key);
-
- if ($baseTranslation instanceof Closure) {
- return $baseTranslation($this, $context, $subKey) ?: $defaultValue;
- }
-
- if (
- $this->getTranslationMessage("$standaloneKey.$subKey") &&
- (!$context || ($regExp = $this->getTranslationMessage("${baseKey}_regexp")) && !preg_match($regExp, $context))
- ) {
- $key = $standaloneKey;
- }
-
- return $this->getTranslationMessage("$key.$subKey", null, $defaultValue);
- }
-
- /**
- * Get the translation of the current week day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- * @param string $keySuffix "", "_short" or "_min"
- * @param string|null $defaultValue default value if translation missing
- *
- * @return string
- */
- public function getTranslatedDayName($context = null, $keySuffix = '', $defaultValue = null)
- {
- return $this->getTranslatedFormByRegExp('weekdays', $keySuffix, $context, $this->dayOfWeek, $defaultValue ?: $this->englishDayOfWeek);
- }
-
- /**
- * Get the translation of the current short week day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- *
- * @return string
- */
- public function getTranslatedShortDayName($context = null)
- {
- return $this->getTranslatedDayName($context, '_short', $this->shortEnglishDayOfWeek);
- }
-
- /**
- * Get the translation of the current abbreviated week day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- *
- * @return string
- */
- public function getTranslatedMinDayName($context = null)
- {
- return $this->getTranslatedDayName($context, '_min', $this->shortEnglishDayOfWeek);
- }
-
- /**
- * Get the translation of the current month day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- * @param string $keySuffix "" or "_short"
- * @param string|null $defaultValue default value if translation missing
- *
- * @return string
- */
- public function getTranslatedMonthName($context = null, $keySuffix = '', $defaultValue = null)
- {
- return $this->getTranslatedFormByRegExp('months', $keySuffix, $context, $this->month - 1, $defaultValue ?: $this->englishMonth);
- }
-
- /**
- * Get the translation of the current short month day name (with context for languages with multiple forms).
- *
- * @param string|null $context whole format string
- *
- * @return string
- */
- public function getTranslatedShortMonthName($context = null)
- {
- return $this->getTranslatedMonthName($context, '_short', $this->shortEnglishMonth);
- }
-
- /**
- * Get/set the day of year.
- *
- * @param int|null $value new value for day of year if using as setter.
- *
- * @return static|CarbonInterface|int
- */
- public function dayOfYear($value = null)
- {
- $dayOfYear = $this->dayOfYear;
-
- return is_null($value) ? $dayOfYear : $this->addDays($value - $dayOfYear);
- }
-
- /**
- * Get/set the weekday from 0 (Sunday) to 6 (Saturday).
- *
- * @param int|null $value new value for weekday if using as setter.
- *
- * @return static|CarbonInterface|int
- */
- public function weekday($value = null)
- {
- $dayOfWeek = ($this->dayOfWeek + 7 - intval($this->getTranslationMessage('first_day_of_week') ?? 0)) % 7;
-
- return is_null($value) ? $dayOfWeek : $this->addDays($value - $dayOfWeek);
- }
-
- /**
- * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday).
- *
- * @param int|null $value new value for weekday if using as setter.
- *
- * @return static|CarbonInterface|int
- */
- public function isoWeekday($value = null)
- {
- $dayOfWeekIso = $this->dayOfWeekIso;
-
- return is_null($value) ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso);
- }
-
- /**
- * Set any unit to a new value without overflowing current other unit given.
- *
- * @param string $valueUnit unit name to modify
- * @param int $value new value for the input unit
- * @param string $overflowUnit unit name to not overflow
- *
- * @return static|CarbonInterface
- */
- public function setUnitNoOverflow($valueUnit, $value, $overflowUnit)
- {
- try {
- $original = $this->copy();
- /** @var CarbonInterface $date */
- $date = $this->$valueUnit($value);
- $end = $original->copy()->endOf($overflowUnit);
- $start = $original->copy()->startOf($overflowUnit);
- if ($date < $start) {
- $date = $date->setDateTimeFrom($start);
- } elseif ($date > $end) {
- $date = $date->setDateTimeFrom($end);
- }
-
- return $date;
- } catch (BadMethodCallException | ReflectionException $exception) {
- throw new InvalidArgumentException("Unknown unit '$valueUnit'", 0, $exception);
- }
- }
-
- /**
- * Add any unit to a new value without overflowing current other unit given.
- *
- * @param string $valueUnit unit name to modify
- * @param int $value amount to add to the input unit
- * @param string $overflowUnit unit name to not overflow
- *
- * @return static|CarbonInterface
- */
- public function addUnitNoOverflow($valueUnit, $value, $overflowUnit)
- {
- return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit + $value, $overflowUnit);
- }
-
- /**
- * Subtract any unit to a new value without overflowing current other unit given.
- *
- * @param string $valueUnit unit name to modify
- * @param int $value amount to subtract to the input unit
- * @param string $overflowUnit unit name to not overflow
- *
- * @return static|CarbonInterface
- */
- public function subUnitNoOverflow($valueUnit, $value, $overflowUnit)
- {
- return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit - $value, $overflowUnit);
- }
-
- /**
- * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed.
- *
- * @param int|null $offset
- *
- * @return int|static|CarbonInterface
- */
- public function utcOffset(int $offset = null)
- {
- if (func_num_args() < 1) {
- return $this->offsetMinutes;
- }
-
- return $this->setTimezone(static::safeCreateDateTimeZone($offset / static::MINUTES_PER_HOUR));
- }
-
- /**
- * Set the date and time all together.
- *
- * @param int $year
- * @param int $month
- * @param int $day
- * @param int $hour
- * @param int $minute
- * @param int $second
- * @param int $microseconds
- *
- * @return static|CarbonInterface
- */
- public function setDateTime($year, $month, $day, $hour, $minute, $second = 0, $microseconds = 0)
- {
- return $this->setDate((int) $year, (int) $month, (int) $day)->setTime((int) $hour, (int) $minute, (int) $second, (int) $microseconds);
- }
-
- /**
- * Set the time by time string.
- *
- * @param string $time
- *
- * @return static|CarbonInterface
- */
- public function setTimeFromTimeString($time)
- {
- if (strpos($time, ':') === false) {
- $time .= ':0';
- }
-
- return $this->modify($time);
- }
-
- /**
- * @alias setTimezone
- *
- * @param \DateTimeZone|string $value
- *
- * @return static|CarbonInterface
- */
- public function timezone($value)
- {
- return $this->setTimezone($value);
- }
-
- /**
- * Set the timezone or returns the timezone name if no arguments passed.
- *
- * @param \DateTimeZone|string $value
- *
- * @return CarbonInterface|string
- */
- public function tz($value = null)
- {
- if (func_num_args() < 1) {
- return $this->tzName;
- }
-
- return $this->setTimezone($value);
- }
-
- /**
- * Set the instance's timezone from a string or object.
- *
- * @param \DateTimeZone|string $value
- *
- * @return static|CarbonInterface
- */
- public function setTimezone($value)
- {
- /** @var static $date */
- $date = parent::setTimezone(static::safeCreateDateTimeZone($value));
- // https://bugs.php.net/bug.php?id=72338
- // just workaround on this bug
- $date->getTimestamp();
-
- return $date;
- }
-
- /**
- * Set the instance's timezone from a string or object and add/subtract the offset difference.
- *
- * @param \DateTimeZone|string $value
- *
- * @return static|CarbonInterface
- */
- public function shiftTimezone($value)
- {
- $offset = $this->offset;
- $date = $this->setTimezone($value);
-
- return $date->addRealMicroseconds(($offset - $date->offset) * static::MICROSECONDS_PER_SECOND);
- }
-
- /**
- * Set the instance's timezone to UTC.
- *
- * @return static|CarbonInterface
- */
- public function utc()
- {
- return $this->setTimezone('UTC');
- }
-
- /**
- * Set the year, month, and date for this instance to that of the passed instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface $date now if null
- *
- * @return static
- */
- public function setDateFrom($date = null)
- {
- $date = $this->resolveCarbon($date);
-
- return $this->setDate($date->year, $date->month, $date->day);
- }
-
- /**
- * Set the hour, minute, second and microseconds for this instance to that of the passed instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface $date now if null
- *
- * @return static
- */
- public function setTimeFrom($date = null)
- {
- $date = $this->resolveCarbon($date);
-
- return $this->setTime($date->hour, $date->minute, $date->second, $date->microsecond);
- }
-
- /**
- * Set the date and time for this instance to that of the passed instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface $date
- *
- * @return static
- */
- public function setDateTimeFrom($date = null)
- {
- $date = $this->resolveCarbon($date);
-
- return $this->modify($date->rawFormat('Y-m-d H:i:s.u'));
- }
-
- /**
- * Get the days of the week
- *
- * @return array
- */
- public static function getDays()
- {
- return static::$days;
- }
-
- ///////////////////////////////////////////////////////////////////
- /////////////////////// WEEK SPECIAL DAYS /////////////////////////
- ///////////////////////////////////////////////////////////////////
-
- /**
- * Get the first day of week
- *
- * @return int
- */
- public static function getWeekStartsAt()
- {
- return static::$weekStartsAt;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
- * 'first_day_of_week' locale setting to change the start of week according to current locale
- * selected and implicitly the end of week.
- *
- * Set the first day of week
- *
- * @param int $day week start day
- *
- * @return void
- */
- public static function setWeekStartsAt($day)
- {
- static::$weekStartsAt = max(0, (7 + $day) % 7);
- }
-
- /**
- * Get the last day of week
- *
- * @return int
- */
- public static function getWeekEndsAt()
- {
- return static::$weekEndsAt;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
- * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
- * start of week according to current locale selected and implicitly the end of week.
- *
- * Set the last day of week
- *
- * @param int $day
- *
- * @return void
- */
- public static function setWeekEndsAt($day)
- {
- static::$weekEndsAt = max(0, (7 + $day) % 7);
- }
-
- /**
- * Get weekend days
- *
- * @return array
- */
- public static function getWeekendDays()
- {
- return static::$weekendDays;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider week-end is always saturday and sunday, and if you have some custom
- * week-end days to handle, give to those days an other name and create a macro for them:
- *
- * ```
- * Carbon::macro('isDayOff', function ($date) {
- * return $date->isSunday() || $date->isMonday();
- * });
- * Carbon::macro('isNotDayOff', function ($date) {
- * return !$date->isDayOff();
- * });
- * if ($someDate->isDayOff()) ...
- * if ($someDate->isNotDayOff()) ...
- * // Add 5 not-off days
- * $count = 5;
- * while ($someDate->isDayOff() || ($count-- > 0)) {
- * $someDate->addDay();
- * }
- * ```
- *
- * Set weekend days
- *
- * @param array $days
- *
- * @return void
- */
- public static function setWeekendDays($days)
- {
- static::$weekendDays = $days;
- }
-
- /**
- * Determine if a time string will produce a relative date.
- *
- * @param string $time
- *
- * @return bool true if time match a relative date, false if absolute or invalid time string
- */
- public static function hasRelativeKeywords($time)
- {
- if (!$time || strtotime($time) === false) {
- return false;
- }
-
- $date1 = new DateTime('2000-01-01T00:00:00Z');
- $date1->modify($time);
- $date2 = new DateTime('2001-12-25T00:00:00Z');
- $date2->modify($time);
-
- return $date1 != $date2;
- }
-
- ///////////////////////////////////////////////////////////////////
- /////////////////////// STRING FORMATTING /////////////////////////
- ///////////////////////////////////////////////////////////////////
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use UTF-8 language packages on every machine.
- *
- * Set if UTF8 will be used for localized date/time.
- *
- * @param bool $utf8
- */
- public static function setUtf8($utf8)
- {
- static::$utf8 = $utf8;
- }
-
- /**
- * Format the instance with the current locale. You can set the current
- * locale using setlocale() http://php.net/setlocale.
- *
- * @param string $format
- *
- * @return string
- */
- public function formatLocalized($format)
- {
- // Check for Windows to find and replace the %e modifier correctly.
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); // @codeCoverageIgnore
- }
-
- $formatted = strftime($format, strtotime($this->toDateTimeString()));
-
- return static::$utf8 ? utf8_encode($formatted) : $formatted;
- }
-
- /**
- * Returns list of locale formats for ISO formatting.
- *
- * @param string|null $locale current locale used if null
- *
- * @return array
- */
- public function getIsoFormats($locale = null)
- {
- return [
- 'LT' => $this->getTranslationMessage('formats.LT', $locale, 'h:mm A'),
- 'LTS' => $this->getTranslationMessage('formats.LTS', $locale, 'h:mm:ss A'),
- 'L' => $this->getTranslationMessage('formats.L', $locale, 'MM/DD/YYYY'),
- 'LL' => $this->getTranslationMessage('formats.LL', $locale, 'MMMM D, YYYY'),
- 'LLL' => $this->getTranslationMessage('formats.LLL', $locale, 'MMMM D, YYYY h:mm A'),
- 'LLLL' => $this->getTranslationMessage('formats.LLLL', $locale, 'dddd, MMMM D, YYYY h:mm A'),
- ];
- }
-
- /**
- * Returns list of calendar formats for ISO formatting.
- *
- * @param string|null $locale current locale used if null
- *
- * @return array
- */
- public function getCalendarFormats($locale = null)
- {
- return [
- 'sameDay' => $this->getTranslationMessage('calendar.sameDay', $locale, '[Today at] LT'),
- 'nextDay' => $this->getTranslationMessage('calendar.nextDay', $locale, '[Tomorrow at] LT'),
- 'nextWeek' => $this->getTranslationMessage('calendar.nextWeek', $locale, 'dddd [at] LT'),
- 'lastDay' => $this->getTranslationMessage('calendar.lastDay', $locale, '[Yesterday at] LT'),
- 'lastWeek' => $this->getTranslationMessage('calendar.lastWeek', $locale, '[Last] dddd [at] LT'),
- 'sameElse' => $this->getTranslationMessage('calendar.sameElse', $locale, 'L'),
- ];
- }
-
- /**
- * Returns list of locale units for ISO formatting.
- *
- * @return array
- */
- public static function getIsoUnits()
- {
- static $units = null;
-
- if ($units === null) {
- $units = [
- 'OD' => ['getAltNumber', ['day']],
- 'OM' => ['getAltNumber', ['month']],
- 'OY' => ['getAltNumber', ['year']],
- 'OH' => ['getAltNumber', ['hour']],
- 'Oh' => ['getAltNumber', ['h']],
- 'Om' => ['getAltNumber', ['minute']],
- 'Os' => ['getAltNumber', ['second']],
- 'D' => 'day',
- 'DD' => ['rawFormat', ['d']],
- 'Do' => ['ordinal', ['day', 'D']],
- 'd' => 'dayOfWeek',
- 'dd' => function (CarbonInterface $date, $originalFormat = null) {
- return $date->getTranslatedMinDayName($originalFormat);
- },
- 'ddd' => function (CarbonInterface $date, $originalFormat = null) {
- return $date->getTranslatedShortDayName($originalFormat);
- },
- 'dddd' => function (CarbonInterface $date, $originalFormat = null) {
- return $date->getTranslatedDayName($originalFormat);
- },
- 'DDD' => 'dayOfYear',
- 'DDDD' => ['getPaddedUnit', ['dayOfYear', 3]],
- 'DDDo' => ['ordinal', ['dayOfYear', 'DDD']],
- 'e' => ['weekday', []],
- 'E' => 'dayOfWeekIso',
- 'H' => ['rawFormat', ['G']],
- 'HH' => ['rawFormat', ['H']],
- 'h' => ['rawFormat', ['g']],
- 'hh' => ['rawFormat', ['h']],
- 'k' => 'noZeroHour',
- 'kk' => ['getPaddedUnit', ['noZeroHour']],
- 'hmm' => ['rawFormat', ['gi']],
- 'hmmss' => ['rawFormat', ['gis']],
- 'Hmm' => ['rawFormat', ['Gi']],
- 'Hmmss' => ['rawFormat', ['Gis']],
- 'm' => 'minute',
- 'mm' => ['rawFormat', ['i']],
- 'a' => 'meridiem',
- 'A' => 'upperMeridiem',
- 's' => 'second',
- 'ss' => ['getPaddedUnit', ['second']],
- 'S' => function (CarbonInterface $date) {
- return strval((string) floor($date->micro / 100000));
- },
- 'SS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro / 10000), 2, '0', STR_PAD_LEFT);
- },
- 'SSS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro / 1000), 3, '0', STR_PAD_LEFT);
- },
- 'SSSS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro / 100), 4, '0', STR_PAD_LEFT);
- },
- 'SSSSS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro / 10), 5, '0', STR_PAD_LEFT);
- },
- 'SSSSSS' => ['getPaddedUnit', ['micro', 6]],
- 'SSSSSSS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro * 10), 7, '0', STR_PAD_LEFT);
- },
- 'SSSSSSSS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro * 100), 8, '0', STR_PAD_LEFT);
- },
- 'SSSSSSSSS' => function (CarbonInterface $date) {
- return str_pad((string) floor($date->micro * 1000), 9, '0', STR_PAD_LEFT);
- },
- 'M' => 'month',
- 'MM' => ['rawFormat', ['m']],
- 'MMM' => function (CarbonInterface $date, $originalFormat = null) {
- $month = $date->getTranslatedShortMonthName($originalFormat);
- $suffix = $date->getTranslationMessage('mmm_suffix');
- if ($suffix && $month !== $date->monthName) {
- $month .= $suffix;
- }
-
- return $month;
- },
- 'MMMM' => function (CarbonInterface $date, $originalFormat = null) {
- return $date->getTranslatedMonthName($originalFormat);
- },
- 'Mo' => ['ordinal', ['month', 'M']],
- 'Q' => 'quarter',
- 'Qo' => ['ordinal', ['quarter', 'M']],
- 'G' => 'isoWeekYear',
- 'GG' => ['getPaddedUnit', ['isoWeekYear']],
- 'GGG' => ['getPaddedUnit', ['isoWeekYear', 3]],
- 'GGGG' => ['getPaddedUnit', ['isoWeekYear', 4]],
- 'GGGGG' => ['getPaddedUnit', ['isoWeekYear', 5]],
- 'g' => 'weekYear',
- 'gg' => ['getPaddedUnit', ['weekYear']],
- 'ggg' => ['getPaddedUnit', ['weekYear', 3]],
- 'gggg' => ['getPaddedUnit', ['weekYear', 4]],
- 'ggggg' => ['getPaddedUnit', ['weekYear', 5]],
- 'W' => 'isoWeek',
- 'WW' => ['getPaddedUnit', ['isoWeek']],
- 'Wo' => ['ordinal', ['isoWeek', 'W']],
- 'w' => 'week',
- 'ww' => ['getPaddedUnit', ['week']],
- 'wo' => ['ordinal', ['week', 'w']],
- 'x' => ['valueOf', []],
- 'X' => 'timestamp',
- 'Y' => 'year',
- 'YY' => ['rawFormat', ['y']],
- 'YYYY' => ['getPaddedUnit', ['year', 4]],
- 'YYYYY' => ['getPaddedUnit', ['year', 5]],
- 'YYYYYY' => function (CarbonInterface $date) {
- return ($date->year < 0 ? '' : '+').$date->getPaddedUnit('year', 6);
- },
- 'z' => 'tzAbbrName',
- 'zz' => 'tzName',
- 'Z' => ['getOffsetString', []],
- 'ZZ' => ['getOffsetString', ['']],
- ];
- }
-
- return $units;
- }
-
- /**
- * Returns a unit of the instance padded with 0 by default or any other string if specified.
- *
- * @param string $unit Carbon unit name
- * @param int $length Length of the output (2 by default)
- * @param string $padString String to use for padding ("0" by default)
- * @param int $padType Side(s) to pad (STR_PAD_LEFT by default)
- *
- * @return string
- */
- public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = STR_PAD_LEFT)
- {
- return ($this->$unit < 0 ? '-' : '').str_pad((string) abs($this->$unit), $length, $padString, $padType);
- }
-
- /**
- * Return a property with its ordinal.
- *
- * @param string $key
- * @param string|null $period
- *
- * @return string
- */
- public function ordinal(string $key, string $period = null): string
- {
- $number = $this->$key;
- $result = $this->translate('ordinal', [
- ':number' => $number,
- ':period' => $period,
- ]);
-
- return strval($result === 'ordinal' ? $number : $result);
- }
-
- /**
- * Return the meridiem of the current time in the current locale.
- *
- * @param bool $isLower if true, returns lowercase variant if available in the current locale.
- *
- * @return string
- */
- public function meridiem(bool $isLower = false): string
- {
- $hour = $this->hour;
- $index = $hour < 12 ? 0 : 1;
-
- if ($isLower) {
- $key = 'meridiem.'.($index + 2);
- $result = $this->translate($key);
-
- if ($result !== $key) {
- return $result;
- }
- }
-
- $key = "meridiem.$index";
- $result = $this->translate($key);
- if ($result === $key) {
- $result = $this->translate('meridiem', [
- ':hour' => $this->hour,
- ':minute' => $this->minute,
- ':isLower' => $isLower,
- ]);
-
- if ($result === 'meridiem') {
- return $isLower ? $this->latinMeridiem : $this->latinUpperMeridiem;
- }
- } elseif ($isLower) {
- $result = mb_strtolower($result);
- }
-
- return $result;
- }
-
- /**
- * Returns the alternative number if available in the current locale.
- *
- * @param string $key date property
- *
- * @return string
- */
- public function getAltNumber(string $key): string
- {
- $number = strlen($key) > 1 ? $this->$key : $this->rawFormat('h');
- $translateKey = "alt_numbers.$number";
- $symbol = $this->translate($translateKey);
-
- if ($symbol !== $translateKey) {
- return $symbol;
- }
-
- if ($number > 99 && $this->translate('alt_numbers.99') !== 'alt_numbers.99') {
- $start = '';
- foreach ([10000, 1000, 100] as $exp) {
- $key = "alt_numbers_pow.$exp";
- if ($number >= $exp && $number < $exp * 10 && ($pow = $this->translate($key)) !== $key) {
- $unit = floor($number / $exp);
- $number -= $unit * $exp;
- $start .= ($unit > 1 ? $this->translate("alt_numbers.$unit") : '').$pow;
- }
- }
- $result = '';
- while ($number) {
- $chunk = $number % 100;
- $result = $this->translate("alt_numbers.$chunk").$result;
- $number = floor($number / 100);
- }
-
- return "$start$result";
- }
-
- if ($number > 9 && $this->translate('alt_numbers.9') !== 'alt_numbers.9') {
- $result = '';
- while ($number) {
- $chunk = $number % 10;
- $result = $this->translate("alt_numbers.$chunk").$result;
- $number = floor($number / 10);
- }
-
- return $result;
- }
-
- return $number;
- }
-
- /**
- * Format in the current language using ISO replacement patterns.
- *
- * @param string $format
- * @param string|null $originalFormat provide context if a chunk has been passed alone
- *
- * @return string
- */
- public function isoFormat(string $format, string $originalFormat = null): string
- {
- $result = '';
- $length = mb_strlen($format);
- $originalFormat = $originalFormat ?: $format;
- $inEscaped = false;
- $formats = null;
- $units = null;
-
- for ($i = 0; $i < $length; $i++) {
- $char = mb_substr($format, $i, 1);
-
- if ($char === '\\') {
- $result .= mb_substr($format, ++$i, 1);
-
- continue;
- }
-
- if ($char === '[' && !$inEscaped) {
- $inEscaped = true;
-
- continue;
- }
-
- if ($char === ']' && $inEscaped) {
- $inEscaped = false;
-
- continue;
- }
-
- if ($inEscaped) {
- $result .= $char;
-
- continue;
- }
-
- $input = mb_substr($format, $i);
-
- if (preg_match('/^(LTS|LT|[Ll]{1,4})/', $input, $match)) {
- if ($formats === null) {
- $formats = $this->getIsoFormats();
- }
-
- $code = $match[0];
- $sequence = $formats[$code] ?? preg_replace_callback(
- '/MMMM|MM|DD|dddd/',
- function ($code) {
- return mb_substr($code[0], 1);
- },
- $formats[strtoupper($code)] ?? ''
- );
- $rest = mb_substr($format, $i + mb_strlen($code));
- $format = mb_substr($format, 0, $i).$sequence.$rest;
- $length = mb_strlen($format);
- $input = $sequence.$rest;
- }
-
- if (preg_match('/^'.CarbonInterface::ISO_FORMAT_REGEXP.'/', $input, $match)) {
- $code = $match[0];
-
- if ($units === null) {
- $units = static::getIsoUnits();
- }
-
- $sequence = $units[$code] ?? '';
-
- if ($sequence instanceof Closure) {
- $sequence = $sequence($this, $originalFormat);
- } elseif (is_array($sequence)) {
- try {
- $sequence = $this->{$sequence[0]}(...$sequence[1]);
- } catch (ReflectionException | InvalidArgumentException | BadMethodCallException $e) {
- $sequence = '';
- }
- } elseif (is_string($sequence)) {
- $sequence = $this->$sequence ?? $code;
- }
-
- $format = mb_substr($format, 0, $i).$sequence.mb_substr($format, $i + mb_strlen($code));
- $i += mb_strlen("$sequence") - 1;
- $length = mb_strlen($format);
- $char = $sequence;
- }
-
- $result .= $char;
- }
-
- return $result;
- }
-
- /**
- * List of replacements from date() format to isoFormat().
- *
- * @return array
- */
- public static function getFormatsToIsoReplacements()
- {
- static $replacements = null;
-
- if ($replacements === null) {
- $replacements = [
- 'd' => true,
- 'D' => 'ddd',
- 'j' => true,
- 'l' => 'dddd',
- 'N' => true,
- 'S' => function ($date) {
- $day = $date->rawFormat('j');
-
- return str_replace("$day", '', $date->isoFormat('Do'));
- },
- 'w' => true,
- 'z' => true,
- 'W' => true,
- 'F' => 'MMMM',
- 'm' => true,
- 'M' => 'MMM',
- 'n' => true,
- 't' => true,
- 'L' => true,
- 'o' => true,
- 'Y' => true,
- 'y' => true,
- 'a' => 'a',
- 'A' => 'A',
- 'B' => true,
- 'g' => true,
- 'G' => true,
- 'h' => true,
- 'H' => true,
- 'i' => true,
- 's' => true,
- 'u' => true,
- 'v' => true,
- 'E' => true,
- 'I' => true,
- 'O' => true,
- 'P' => true,
- 'Z' => true,
- 'c' => true,
- 'r' => true,
- 'U' => true,
- ];
- }
-
- return $replacements;
- }
-
- /**
- * Format as ->format() do (using date replacements patterns from http://php.net/manual/fr/function.date.php)
- * but translate words whenever possible (months, day names, etc.) using the current locale.
- *
- * @param string $format
- *
- * @return string
- */
- public function translatedFormat(string $format): string
- {
- $replacements = static::getFormatsToIsoReplacements();
- $context = '';
- $isoFormat = '';
- $length = mb_strlen($format);
-
- for ($i = 0; $i < $length; $i++) {
- $char = mb_substr($format, $i, 1);
-
- if ($char === '\\') {
- $replacement = mb_substr($format, $i, 2);
- $isoFormat .= $replacement;
- $i++;
-
- continue;
- }
-
- if (!isset($replacements[$char])) {
- $replacement = preg_match('/^[A-Za-z]$/', $char) ? "\\$char" : $char;
- $isoFormat .= $replacement;
- $context .= $replacement;
-
- continue;
- }
-
- $replacement = $replacements[$char];
-
- if ($replacement === true) {
- static $contextReplacements = null;
-
- if ($contextReplacements === null) {
- $contextReplacements = [
- 'm' => 'MM',
- 'd' => 'DD',
- 't' => 'D',
- 'j' => 'D',
- 'N' => 'e',
- 'w' => 'e',
- 'n' => 'M',
- 'o' => 'YYYY',
- 'Y' => 'YYYY',
- 'y' => 'YY',
- 'g' => 'h',
- 'G' => 'H',
- 'h' => 'hh',
- 'H' => 'HH',
- 'i' => 'mm',
- 's' => 'ss',
- ];
- }
-
- $isoFormat .= '['.$this->rawFormat($char).']';
- $context .= $contextReplacements[$char] ?? ' ';
-
- continue;
- }
-
- if ($replacement instanceof Closure) {
- $replacement = '['.$replacement($this).']';
- $isoFormat .= $replacement;
- $context .= $replacement;
-
- continue;
- }
-
- $isoFormat .= $replacement;
- $context .= $replacement;
- }
-
- return $this->isoFormat($isoFormat, $context);
- }
-
- /**
- * Returns the offset hour and minute formatted with +/- and a given separator (":" by default).
- * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first
- * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something
- * like "-12:00".
- *
- * @param string $separator string to place between hours and minutes (":" by default)
- *
- * @return string
- */
- public function getOffsetString($separator = ':')
- {
- $second = $this->getOffset();
- $symbol = $second < 0 ? '-' : '+';
- $minute = abs($second) / static::SECONDS_PER_MINUTE;
- $hour = str_pad((string) floor($minute / static::MINUTES_PER_HOUR), 2, '0', STR_PAD_LEFT);
- $minute = str_pad((string) ($minute % static::MINUTES_PER_HOUR), 2, '0', STR_PAD_LEFT);
-
- return "$symbol$hour$separator$minute";
- }
-
- protected static function executeStaticCallable($macro, ...$parameters)
- {
- if ($macro instanceof Closure) {
- return call_user_func_array(Closure::bind($macro, null, get_called_class()), $parameters);
- }
-
- return call_user_func_array($macro, $parameters);
- }
-
- /**
- * Dynamically handle calls to the class.
- *
- * @param string $method magic method name called
- * @param array $parameters parameters list
- *
- * @throws \BadMethodCallException
- *
- * @return mixed
- */
- public static function __callStatic($method, $parameters)
- {
- if (!static::hasMacro($method)) {
- foreach (static::getGenericMacros() as $callback) {
- try {
- return static::executeStaticCallable($callback, $method, ...$parameters);
- } catch (BadMethodCallException $exception) {
- continue;
- }
- }
- if (static::isStrictModeEnabled()) {
- throw new BadMethodCallException(sprintf(
- 'Method %s::%s does not exist.', static::class, $method
- ));
- }
-
- return null;
- }
-
- return static::executeStaticCallable(static::$globalMacros[$method], ...$parameters);
- }
-
- /**
- * Set specified unit to new given value.
- *
- * @param string $unit year, month, day, hour, minute, second or microsecond
- * @param int $value new value for given unit
- *
- * @return static
- */
- public function setUnit($unit, $value = null)
- {
- $unit = static::singularUnit($unit);
- $dateUnits = ['year', 'month', 'day'];
- if (in_array($unit, $dateUnits)) {
- return $this->setDate(...array_map(function ($name) use ($unit, $value) {
- return (int) ($name === $unit ? $value : $this->$name);
- }, $dateUnits));
- }
-
- $units = ['hour', 'minute', 'second', 'micro'];
- if ($unit === 'millisecond' || $unit === 'milli') {
- $value *= 1000;
- $unit = 'micro';
- } elseif ($unit === 'microsecond') {
- $unit = 'micro';
- }
-
- return $this->setTime(...array_map(function ($name) use ($unit, $value) {
- return (int) ($name === $unit ? $value : $this->$name);
- }, $units));
- }
-
- /**
- * Returns standardized singular of a given singular/plural unit name (in English).
- *
- * @param string $unit
- *
- * @return string
- */
- public static function singularUnit(string $unit): string
- {
- $unit = rtrim(strtolower($unit), 's');
-
- if ($unit === 'centurie') {
- return 'century';
- }
-
- if ($unit === 'millennia') {
- return 'millennium';
- }
-
- return $unit;
- }
-
- /**
- * Returns standardized plural of a given singular/plural unit name (in English).
- *
- * @param string $unit
- *
- * @return string
- */
- public static function pluralUnit(string $unit): string
- {
- $unit = rtrim(strtolower($unit), 's');
-
- if ($unit === 'century') {
- return 'centuries';
- }
-
- if ($unit === 'millennium' || $unit === 'millennia') {
- return 'millennia';
- }
-
- return "${unit}s";
- }
-
- protected function executeCallable($macro, ...$parameters)
- {
- if ($macro instanceof Closure) {
- return call_user_func_array($macro->bindTo($this, static::class), $parameters);
- }
-
- return call_user_func_array($macro, $parameters);
- }
-
- protected static function getGenericMacros()
- {
- foreach (static::$globalGenericMacros as $list) {
- foreach ($list as $macro) {
- yield $macro;
- }
- }
- }
-
- /**
- * Dynamically handle calls to the class.
- *
- * @param string $method magic method name called
- * @param array $parameters parameters list
- *
- * @throws \BadMethodCallException|\ReflectionException
- *
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- $diffSizes = [
- // @mode diffForHumans
- 'short' => true,
- // @mode diffForHumans
- 'long' => false,
- ];
- $diffSyntaxModes = [
- // @call diffForHumans
- 'Absolute' => CarbonInterface::DIFF_ABSOLUTE,
- // @call diffForHumans
- 'Relative' => CarbonInterface::DIFF_RELATIVE_AUTO,
- // @call diffForHumans
- 'RelativeToNow' => CarbonInterface::DIFF_RELATIVE_TO_NOW,
- // @call diffForHumans
- 'RelativeToOther' => CarbonInterface::DIFF_RELATIVE_TO_OTHER,
- ];
- $sizePattern = implode('|', array_keys($diffSizes));
- $syntaxPattern = implode('|', array_keys($diffSyntaxModes));
- if (preg_match("/^(?<size>$sizePattern)(?<syntax>$syntaxPattern)DiffForHumans$/", $method, $match)) {
- $dates = array_filter($parameters, function ($parameter) {
- return $parameter instanceof DateTimeInterface;
- });
- $other = null;
- if (count($dates)) {
- $key = key($dates);
- $other = current($dates);
- array_splice($parameters, $key, 1);
- }
-
- return $this->diffForHumans($other, $diffSyntaxModes[$match['syntax']], $diffSizes[$match['size']], ...$parameters);
- }
-
- $action = substr($method, 0, 4);
- if ($action !== 'ceil') {
- $action = substr($method, 0, 5);
- }
- if (in_array($action, ['round', 'floor', 'ceil'])) {
- return $this->{$action.'Unit'}(substr($method, strlen($action)), ...$parameters);
- }
-
- $unit = rtrim($method, 's');
- if (substr($unit, 0, 2) === 'is') {
- $word = substr($unit, 2);
- if (in_array($word, static::$days)) {
- return $this->isDayOfWeek($word);
- }
- switch ($word) {
- // @call is Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
- case 'Utc':
- case 'UTC':
- return $this->utc;
- // @call is Check if the current instance has non-UTC timezone.
- case 'Local':
- return $this->local;
- // @call is Check if the current instance is a valid date.
- case 'Valid':
- return $this->year !== 0;
- // @call is Check if the current instance is in a daylight saving time.
- case 'DST':
- return $this->dst;
- }
- }
-
- $action = substr($unit, 0, 3);
- $overflow = null;
- if ($action === 'set') {
- $unit = strtolower(substr($unit, 3));
- }
-
- if (in_array($unit, static::$units)) {
- return $this->setUnit($unit, ...$parameters);
- }
-
- if ($action === 'add' || $action === 'sub') {
- $unit = substr($unit, 3);
- if (substr($unit, 0, 4) === 'Real') {
- $unit = static::singularUnit(substr($unit, 4));
-
- return $this->{"${action}RealUnit"}($unit, ...$parameters);
- }
-
- if (preg_match('/^(Month|Quarter|Year|Decade|Century|Centurie|Millennium|Millennia)s?(No|With|Without|WithNo)Overflow$/', $unit, $match)) {
- $unit = $match[1];
- $overflow = $match[2] === 'With';
- }
- $unit = static::singularUnit($unit);
- }
-
- if (static::isModifiableUnit($unit)) {
- return $this->{"${action}Unit"}($unit, $parameters[0] ?? 1, $overflow);
- }
-
- $sixFirstLetters = substr($unit, 0, 6);
- $factor = -1;
-
- if ($sixFirstLetters === 'isLast') {
- $sixFirstLetters = 'isNext';
- $factor = 1;
- }
-
- if ($sixFirstLetters === 'isNext') {
- $lowerUnit = strtolower(substr($unit, 6));
-
- if (static::isModifiableUnit($lowerUnit)) {
- return $this->copy()->addUnit($lowerUnit, $factor, false)->isSameUnit($lowerUnit, ...$parameters);
- }
- }
-
- if ($sixFirstLetters === 'isSame') {
- try {
- return $this->isSameUnit(strtolower(substr($unit, 6)), ...$parameters);
- } catch (InvalidArgumentException $exception) {
- // Try next
- }
- }
-
- if (substr($unit, 0, 9) === 'isCurrent') {
- try {
- return $this->isCurrentUnit(strtolower(substr($unit, 9)));
- } catch (InvalidArgumentException | BadMethodCallException $exception) {
- // Try macros
- }
- }
-
- if (!static::hasMacro($method)) {
- foreach ([$this->localGenericMacros ?: [], static::getGenericMacros()] as $list) {
- foreach ($list as $callback) {
- try {
- return $this->executeCallable($callback, $method, ...$parameters);
- } catch (BadMethodCallException $exception) {
- continue;
- }
- }
- }
- if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
- throw new BadMethodCallException("Method $method does not exist.");
- }
-
- return null;
- }
-
- return $this->executeCallable(($this->localMacros ?? [])[$method] ?? static::$globalMacros[$method], ...$parameters);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\Carbon;
-use Carbon\CarbonImmutable;
-use Carbon\CarbonInterface;
-use Carbon\CarbonInterval;
-use Carbon\CarbonPeriod;
-use Carbon\Translator;
-use Closure;
-use DateInterval;
-use DateTimeInterface;
-
-/**
- * Trait Difference.
- *
- * Depends on the following methods:
- *
- * @method bool lessThan($date)
- * @method DateInterval diff(\DateTimeInterface $date, bool $absolute = false)
- * @method CarbonInterface copy()
- * @method CarbonInterface resolveCarbon()
- * @method static Translator translator()
- */
-trait Difference
-{
- /**
- * @param DateInterval $diff
- * @param bool $absolute
- *
- * @return CarbonInterval
- */
- protected static function fixDiffInterval(DateInterval $diff, $absolute)
- {
- $diff = CarbonInterval::instance($diff);
- // Work-around for https://bugs.php.net/bug.php?id=77145
- // @codeCoverageIgnoreStart
- if ($diff->f > 0 && $diff->y === -1 && $diff->m === 11 && $diff->d >= 27 && $diff->h === 23 && $diff->i === 59 && $diff->s === 59) {
- $diff->y = 0;
- $diff->m = 0;
- $diff->d = 0;
- $diff->h = 0;
- $diff->i = 0;
- $diff->s = 0;
- $diff->f = (1000000 - round($diff->f * 1000000)) / 1000000;
- $diff->invert();
- } elseif ($diff->f < 0) {
- if ($diff->s !== 0 || $diff->i !== 0 || $diff->h !== 0 || $diff->d !== 0 || $diff->m !== 0 || $diff->y !== 0) {
- $diff->f = (round($diff->f * 1000000) + 1000000) / 1000000;
- $diff->s--;
-
- if ($diff->s < 0) {
- $diff->s += 60;
- $diff->i--;
-
- if ($diff->i < 0) {
- $diff->i += 60;
- $diff->h--;
-
- if ($diff->h < 0) {
- $diff->h += 24;
- $diff->d--;
-
- if ($diff->d < 0) {
- $diff->d += 30;
- $diff->m--;
-
- if ($diff->m < 0) {
- $diff->m += 12;
- $diff->y--;
- }
- }
- }
- }
- }
- } else {
- $diff->f *= -1;
- $diff->invert();
- }
- }
- // @codeCoverageIgnoreEnd
-
- if ($absolute && $diff->invert) {
- $diff->invert();
- }
-
- return $diff;
- }
-
- /**
- * Get the difference as a CarbonInterval instance
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return CarbonInterval
- */
- public function diffAsCarbonInterval($date = null, $absolute = true)
- {
- return static::fixDiffInterval($this->diff($this->resolveCarbon($date), $absolute), $absolute);
- }
-
- /**
- * Get the difference in years
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInYears($date = null, $absolute = true)
- {
- return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y');
- }
-
- /**
- * Get the difference in months
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMonths($date = null, $absolute = true)
- {
- $date = $this->resolveCarbon($date);
-
- return $this->diffInYears($date, $absolute) * static::MONTHS_PER_YEAR + (int) $this->diff($date, $absolute)->format('%r%m');
- }
-
- /**
- * Get the difference in weeks
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInWeeks($date = null, $absolute = true)
- {
- return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK);
- }
-
- /**
- * Get the difference in days
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInDays($date = null, $absolute = true)
- {
- return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%a');
- }
-
- /**
- * Get the difference in days using a filter closure
- *
- * @param Closure $callback
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true)
- {
- return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute);
- }
-
- /**
- * Get the difference in hours using a filter closure
- *
- * @param Closure $callback
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true)
- {
- return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute);
- }
-
- /**
- * Get the difference by the given interval using a filter closure
- *
- * @param CarbonInterval $ci An interval to traverse by
- * @param Closure $callback
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true)
- {
- $start = $this;
- $end = $this->resolveCarbon($date);
- $inverse = false;
-
- if ($end < $start) {
- $start = $end;
- $end = $this;
- $inverse = true;
- }
-
- $options = CarbonPeriod::EXCLUDE_END_DATE | ($this->isMutable() ? 0 : CarbonPeriod::IMMUTABLE);
- $diff = $ci->toPeriod($start, $end, $options)->filter($callback)->count();
-
- return $inverse && !$absolute ? -$diff : $diff;
- }
-
- /**
- * Get the difference in weekdays
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInWeekdays($date = null, $absolute = true)
- {
- return $this->diffInDaysFiltered(function (CarbonInterface $date) {
- return $date->isWeekday();
- }, $date, $absolute);
- }
-
- /**
- * Get the difference in weekend days using a filter
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInWeekendDays($date = null, $absolute = true)
- {
- return $this->diffInDaysFiltered(function (CarbonInterface $date) {
- return $date->isWeekend();
- }, $date, $absolute);
- }
-
- /**
- * Get the difference in hours.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInHours($date = null, $absolute = true)
- {
- return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
- }
-
- /**
- * Get the difference in hours using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealHours($date = null, $absolute = true)
- {
- return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
- }
-
- /**
- * Get the difference in minutes.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMinutes($date = null, $absolute = true)
- {
- return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
- }
-
- /**
- * Get the difference in minutes using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealMinutes($date = null, $absolute = true)
- {
- return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
- }
-
- /**
- * Get the difference in seconds.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInSeconds($date = null, $absolute = true)
- {
- $diff = $this->diff($this->resolveCarbon($date));
- if ($diff->days === 0) {
- $diff = static::fixDiffInterval($diff, $absolute);
- }
- $value = ((($diff->days * static::HOURS_PER_DAY) +
- $diff->h) * static::MINUTES_PER_HOUR +
- $diff->i) * static::SECONDS_PER_MINUTE +
- $diff->s;
-
- return $absolute || !$diff->invert ? $value : -$value;
- }
-
- /**
- * Get the difference in microseconds.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMicroseconds($date = null, $absolute = true)
- {
- $diff = $this->diff($this->resolveCarbon($date));
- $value = (int) round((((($diff->days * static::HOURS_PER_DAY) +
- $diff->h) * static::MINUTES_PER_HOUR +
- $diff->i) * static::SECONDS_PER_MINUTE +
- ($diff->f + $diff->s)) * static::MICROSECONDS_PER_SECOND);
-
- return $absolute || !$diff->invert ? $value : -$value;
- }
-
- /**
- * Get the difference in milliseconds.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInMilliseconds($date = null, $absolute = true)
- {
- return (int) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
- }
-
- /**
- * Get the difference in seconds using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealSeconds($date = null, $absolute = true)
- {
- /** @var CarbonInterface $date */
- $date = $this->resolveCarbon($date);
- $value = $date->getTimestamp() - $this->getTimestamp();
-
- return $absolute ? abs($value) : $value;
- }
-
- /**
- * Get the difference in microseconds using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealMicroseconds($date = null, $absolute = true)
- {
- /** @var CarbonInterface $date */
- $date = $this->resolveCarbon($date);
- $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND +
- $date->micro - $this->micro;
-
- return $absolute ? abs($value) : $value;
- }
-
- /**
- * Get the difference in milliseconds using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return int
- */
- public function diffInRealMilliseconds($date = null, $absolute = true)
- {
- return (int) ($this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
- }
-
- /**
- * Get the difference in seconds as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInSeconds($date = null, $absolute = true)
- {
- return $this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND;
- }
-
- /**
- * Get the difference in minutes as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInMinutes($date = null, $absolute = true)
- {
- return $this->floatDiffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
- }
-
- /**
- * Get the difference in hours as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInHours($date = null, $absolute = true)
- {
- return $this->floatDiffInMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
- }
-
- /**
- * Get the difference in days as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInDays($date = null, $absolute = true)
- {
- $hoursDiff = $this->floatDiffInHours($date, $absolute);
-
- return ($hoursDiff < 0 ? -1 : 1) * $this->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
- }
-
- /**
- * Get the difference in months as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInMonths($date = null, $absolute = true)
- {
- $start = $this;
- $end = $this->resolveCarbon($date);
- $ascending = ($start <= $end);
- $sign = $absolute || $ascending ? 1 : -1;
- if (!$ascending) {
- $_end = $start;
- $start = $end;
- $end = $_end;
- unset($_end);
- }
- $monthsDiff = $start->diffInMonths($end);
- /** @var Carbon|CarbonImmutable $floorEnd */
- $floorEnd = $start->copy()->addMonths($monthsDiff);
-
- if ($floorEnd >= $end) {
- return $sign * $monthsDiff;
- }
-
- /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
- $startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
-
- if ($startOfMonthAfterFloorEnd > $end) {
- return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInMonth);
- }
-
- return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInDays($end) / $end->daysInMonth);
- }
-
- /**
- * Get the difference in year as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInYears($date = null, $absolute = true)
- {
- $start = $this;
- $end = $this->resolveCarbon($date);
- $ascending = ($start <= $end);
- $sign = $absolute || $ascending ? 1 : -1;
- if (!$ascending) {
- $_end = $start;
- $start = $end;
- $end = $_end;
- unset($_end);
- }
- $yearsDiff = $start->diffInYears($end);
- /** @var Carbon|CarbonImmutable $floorEnd */
- $floorEnd = $start->copy()->addYears($yearsDiff);
-
- if ($floorEnd >= $end) {
- return $sign * $yearsDiff;
- }
-
- /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
- $startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
-
- if ($startOfYearAfterFloorEnd > $end) {
- return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInYear);
- }
-
- return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInDays($end) / $end->daysInYear);
- }
-
- /**
- * Get the difference in seconds as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealSeconds($date = null, $absolute = true)
- {
- return $this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND;
- }
-
- /**
- * Get the difference in minutes as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealMinutes($date = null, $absolute = true)
- {
- return $this->floatDiffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
- }
-
- /**
- * Get the difference in hours as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealHours($date = null, $absolute = true)
- {
- return $this->floatDiffInRealMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
- }
-
- /**
- * Get the difference in days as float (microsecond-precision).
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealDays($date = null, $absolute = true)
- {
- $hoursDiff = $this->floatDiffInRealHours($date, $absolute);
-
- return ($hoursDiff < 0 ? -1 : 1) * $this->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
- }
-
- /**
- * Get the difference in months as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealMonths($date = null, $absolute = true)
- {
- $start = $this;
- $end = $this->resolveCarbon($date);
- $ascending = ($start <= $end);
- $sign = $absolute || $ascending ? 1 : -1;
- if (!$ascending) {
- $_end = $start;
- $start = $end;
- $end = $_end;
- unset($_end);
- }
- $monthsDiff = $start->diffInMonths($end);
- /** @var Carbon|CarbonImmutable $floorEnd */
- $floorEnd = $start->copy()->addMonths($monthsDiff);
-
- if ($floorEnd >= $end) {
- return $sign * $monthsDiff;
- }
-
- /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
- $startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
-
- if ($startOfMonthAfterFloorEnd > $end) {
- return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInMonth);
- }
-
- return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInMonth);
- }
-
- /**
- * Get the difference in year as float (microsecond-precision) using timestamps.
- *
- * @param Carbon|\DateTimeInterface|string|null $date
- * @param bool $absolute Get the absolute of the difference
- *
- * @return float
- */
- public function floatDiffInRealYears($date = null, $absolute = true)
- {
- $start = $this;
- $end = $this->resolveCarbon($date);
- $ascending = ($start <= $end);
- $sign = $absolute || $ascending ? 1 : -1;
- if (!$ascending) {
- $_end = $start;
- $start = $end;
- $end = $_end;
- unset($_end);
- }
- $yearsDiff = $start->diffInYears($end);
- /** @var Carbon|CarbonImmutable $floorEnd */
- $floorEnd = $start->copy()->addYears($yearsDiff);
-
- if ($floorEnd >= $end) {
- return $sign * $yearsDiff;
- }
-
- /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
- $startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
-
- if ($startOfYearAfterFloorEnd > $end) {
- return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInYear);
- }
-
- return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInYear);
- }
-
- /**
- * The number of seconds since midnight.
- *
- * @return int
- */
- public function secondsSinceMidnight()
- {
- return $this->diffInSeconds($this->copy()->startOfDay());
- }
-
- /**
- * The number of seconds until 23:59:59.
- *
- * @return int
- */
- public function secondsUntilEndOfDay()
- {
- return $this->diffInSeconds($this->copy()->endOfDay());
- }
-
- /**
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- *
- * @example
- * ```
- * echo Carbon::tomorrow()->diffForHumans() . "\n";
- * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
- * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
- * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
- * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
- * ```
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
- {
- /* @var CarbonInterface $this */
- if (is_array($other)) {
- $other['syntax'] = array_key_exists('syntax', $other) ? $other['syntax'] : $syntax;
- $syntax = $other;
- $other = $syntax['other'] ?? null;
- }
-
- $intSyntax = &$syntax;
- if (is_array($syntax)) {
- $syntax['syntax'] = $syntax['syntax'] ?? null;
- $intSyntax = &$syntax['syntax'];
- }
- $intSyntax = (int) ($intSyntax === null ? static::DIFF_RELATIVE_AUTO : $intSyntax);
- $intSyntax = $intSyntax === static::DIFF_RELATIVE_AUTO && $other === null ? static::DIFF_RELATIVE_TO_NOW : $intSyntax;
-
- $parts = min(7, max(1, (int) $parts));
-
- return $this->diffAsCarbonInterval($other, false)
- ->setLocalTranslator($this->getLocalTranslator())
- ->forHumans($syntax, (bool) $short, $parts, $options ?? $this->localHumanDiffOptions ?? static::getHumanDiffOptions());
- }
-
- /**
- * @alias diffForHumans
- *
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
- {
- return $this->diffForHumans($other, $syntax, $short, $parts, $options);
- }
-
- /**
- * @alias diffForHumans
- *
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- */
- public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
- {
- return $this->diffForHumans($other, $syntax, $short, $parts, $options);
- }
-
- /**
- * Get the difference in a human readable format in the current locale from an other
- * instance given (or now if null given) to current instance.
- *
- * When comparing a value in the past to default now:
- * 1 hour from now
- * 5 months from now
- *
- * When comparing a value in the future to default now:
- * 1 hour ago
- * 5 months ago
- *
- * When comparing a value in the past to another value:
- * 1 hour after
- * 5 months after
- *
- * When comparing a value in the future to another value:
- * 1 hour before
- * 5 months before
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
- {
- if (!$syntax && !$other) {
- $syntax = CarbonInterface::DIFF_RELATIVE_TO_NOW;
- }
-
- return $this->resolveCarbon($other)->diffForHumans($this, $syntax, $short, $parts, $options);
- }
-
- /**
- * @alias to
- *
- * Get the difference in a human readable format in the current locale from an other
- * instance given (or now if null given) to current instance.
- *
- * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
- * if null passed, now will be used as comparison reference;
- * if any other type, it will be converted to date and used as reference.
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * - 'other' entry (see above)
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
- {
- return $this->to($other, $syntax, $short, $parts, $options);
- }
-
- /**
- * Get the difference in a human readable format in the current locale from current
- * instance to now.
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single unit)
- * @param int $options human diff options
- *
- * @return string
- */
- public function fromNow($syntax = null, $short = false, $parts = 1, $options = null)
- {
- $other = null;
-
- if ($syntax instanceof DateTimeInterface) {
- [$other, $syntax, $short, $parts, $options] = array_pad(func_get_args(), 5, null);
- }
-
- return $this->from($other, $syntax, $short, $parts, $options);
- }
-
- /**
- * Get the difference in a human readable format in the current locale from an other
- * instance given to now
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single part)
- * @param int $options human diff options
- *
- * @return string
- */
- public function toNow($syntax = null, $short = false, $parts = 1, $options = null)
- {
- return $this->to(null, $syntax, $short, $parts, $options);
- }
-
- /**
- * Get the difference in a human readable format in the current locale from an other
- * instance given to now
- *
- * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
- * - 'syntax' entry (see below)
- * - 'short' entry (see below)
- * - 'parts' entry (see below)
- * - 'options' entry (see below)
- * - 'join' entry determines how to join multiple parts of the string
- * ` - if $join is a string, it's used as a joiner glue
- * ` - if $join is a callable/closure, it get the list of string and should return a string
- * ` - if $join is an array, the first item will be the default glue, and the second item
- * ` will be used instead of the glue for the last item
- * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
- * ` - if $join is missing, a space will be used as glue
- * if int passed, it add modifiers:
- * Possible values:
- * - CarbonInterface::DIFF_ABSOLUTE no modifiers
- * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
- * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
- * Default value: CarbonInterface::DIFF_ABSOLUTE
- * @param bool $short displays short format of time units
- * @param int $parts maximum number of parts to display (default value: 1: single part)
- * @param int $options human diff options
- *
- * @return string
- */
- public function ago($syntax = null, $short = false, $parts = 1, $options = null)
- {
- $other = null;
-
- if ($syntax instanceof DateTimeInterface) {
- [$other, $syntax, $short, $parts, $options] = array_pad(func_get_args(), 5, null);
- }
-
- return $this->from($other, $syntax, $short, $parts, $options);
- }
-
- /**
- * Get the difference in a human readable format in the current locale from current instance to an other
- * instance given (or now if null given).
- *
- * @return string
- */
- public function timespan($other = null, $timezone = null)
- {
- if (!$other instanceof DateTimeInterface) {
- $other = static::parse($other, $timezone);
- }
-
- return $this->diffForHumans($other, [
- 'join' => ', ',
- 'syntax' => CarbonInterface::DIFF_ABSOLUTE,
- 'options' => CarbonInterface::NO_ZERO_DIFF,
- 'parts' => -1,
- ]);
- }
-
- /**
- * Returns either the close date "Friday 15h30", or a calendar date "10/09/2017" is farthest than 7 days from now.
- *
- * @param Carbon|\DateTimeInterface|string|null $referenceTime
- * @param array $formats
- *
- * @return string
- */
- public function calendar($referenceTime = null, array $formats = [])
- {
- /** @var CarbonInterface $current */
- $current = $this->copy()->startOfDay();
- /** @var CarbonInterface $other */
- $other = $this->resolveCarbon($referenceTime)->copy()->setTimezone($this->getTimezone())->startOfDay();
- $diff = $other->diffInDays($current, false);
- $format = $diff < -6 ? 'sameElse' : (
- $diff < -1 ? 'lastWeek' : (
- $diff < 0 ? 'lastDay' : (
- $diff < 1 ? 'sameDay' : (
- $diff < 2 ? 'nextDay' : (
- $diff < 7 ? 'nextWeek' : 'sameElse'
- )
- )
- )
- )
- );
- $format = array_merge($this->getCalendarFormats(), $formats)[$format];
- if ($format instanceof Closure) {
- $format = $format($current, $other) ?? '';
- }
-
- return $this->isoFormat(strval($format));
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-use Carbon\Language;
-use Carbon\Translator;
-use Closure;
-use InvalidArgumentException;
-use Symfony\Component\Translation\TranslatorBagInterface;
-use Symfony\Component\Translation\TranslatorInterface;
-
-/**
- * Trait Localization.
- *
- * Embed default and locale translators and translation base methods.
- */
-trait Localization
-{
- /**
- * Default translator.
- *
- * @var \Symfony\Component\Translation\TranslatorInterface
- */
- protected static $translator;
-
- /**
- * Specific translator of the current instance.
- *
- * @var \Symfony\Component\Translation\TranslatorInterface
- */
- protected $localTranslator;
-
- /**
- * Options for diffForHumans().
- *
- * @var int
- */
- protected static $humanDiffOptions = CarbonInterface::NO_ZERO_DIFF;
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * @param int $humanDiffOptions
- */
- public static function setHumanDiffOptions($humanDiffOptions)
- {
- static::$humanDiffOptions = $humanDiffOptions;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * @param int $humanDiffOption
- */
- public static function enableHumanDiffOption($humanDiffOption)
- {
- static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * @param int $humanDiffOption
- */
- public static function disableHumanDiffOption($humanDiffOption)
- {
- static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption;
- }
-
- /**
- * Return default humanDiff() options (merged flags as integer).
- *
- * @return int
- */
- public static function getHumanDiffOptions()
- {
- return static::$humanDiffOptions;
- }
-
- /**
- * Initialize the default translator instance if necessary.
- *
- * @return \Symfony\Component\Translation\TranslatorInterface
- */
- protected static function translator()
- {
- if (static::$translator === null) {
- static::$translator = Translator::get();
- }
-
- return static::$translator;
- }
-
- /**
- * Get the default translator instance in use.
- *
- * @return \Symfony\Component\Translation\TranslatorInterface
- */
- public static function getTranslator()
- {
- return static::translator();
- }
-
- /**
- * Set the default translator instance to use.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- *
- * @return void
- */
- public static function setTranslator(TranslatorInterface $translator)
- {
- static::$translator = $translator;
- }
-
- /**
- * Get the translator of the current instance or the default if none set.
- *
- * @return \Symfony\Component\Translation\TranslatorInterface
- */
- public function getLocalTranslator()
- {
- return $this->localTranslator ?: static::translator();
- }
-
- /**
- * Set the translator for the current instance.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- *
- * @return $this
- */
- public function setLocalTranslator(TranslatorInterface $translator)
- {
- $this->localTranslator = $translator;
-
- return $this;
- }
-
- /**
- * Returns raw translation message for a given key.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use
- * @param string $key key to find
- * @param string|null $locale current locale used if null
- * @param string|null $default default value if translation returns the key
- *
- * @return string
- */
- public static function getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null)
- {
- if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) {
- throw new InvalidArgumentException(
- 'Translator does not implement '.TranslatorInterface::class.' and '.TranslatorBagInterface::class.'.'
- );
- }
-
- $result = $translator->getCatalogue($locale ?? $translator->getLocale())->get($key);
-
- return $result === $key ? $default : $result;
- }
-
- /**
- * Returns raw translation message for a given key.
- *
- * @param string $key key to find
- * @param string|null $locale current locale used if null
- * @param string|null $default default value if translation returns the key
- * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use
- *
- * @return string
- */
- public function getTranslationMessage(string $key, string $locale = null, string $default = null, $translator = null)
- {
- return static::getTranslationMessageWith($translator ?: $this->getLocalTranslator(), $key, $locale, $default);
- }
-
- /**
- * Translate using translation string or callback available.
- *
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- * @param string $key
- * @param array $parameters
- * @param null $number
- *
- * @return string
- */
- public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string
- {
- $message = static::getTranslationMessageWith($translator, $key, null, $key);
- if ($message instanceof Closure) {
- return (string) $message(...array_values($parameters));
- }
-
- if ($number !== null) {
- $parameters['%count%'] = $number;
- }
- if (isset($parameters['%count%'])) {
- $parameters[':count'] = $parameters['%count%'];
- }
-
- return (string) $translator->transChoice($key, $number, $parameters);
- }
-
- /**
- * Translate using translation string or callback available.
- *
- * @param string $key
- * @param array $parameters
- * @param null $number
- * @param \Symfony\Component\Translation\TranslatorInterface $translator
- *
- * @return string
- */
- public function translate(string $key, array $parameters = [], $number = null, TranslatorInterface $translator = null): string
- {
- return static::translateWith($translator ?: $this->getLocalTranslator(), $key, $parameters, $number);
- }
-
- /**
- * Translate a time string from a locale to an other.
- *
- * @param string $timeString time string to translate
- * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default)
- * @param string|null $to output locale of the result returned (`"en"` by default)
- * @param int $mode specify what to translate with options:
- * - CarbonInterface::TRANSLATE_ALL (default)
- * - CarbonInterface::TRANSLATE_MONTHS
- * - CarbonInterface::TRANSLATE_DAYS
- * - CarbonInterface::TRANSLATE_UNITS
- * - CarbonInterface::TRANSLATE_MERIDIEM
- * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS
- *
- * @return string
- */
- public static function translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL)
- {
- $from = $from ?: static::getLocale();
- $to = $to ?: 'en';
-
- if ($from === $to) {
- return $timeString;
- }
-
- $cleanWord = function ($word) {
- $word = str_replace([':count', '%count', ':time'], '', $word);
- $word = preg_replace('/({\d+(,(\d+|Inf))?}|[\[\]]\d+(,(\d+|Inf))?[\[\]])/', '', $word);
-
- return trim($word);
- };
-
- $fromTranslations = [];
- $toTranslations = [];
-
- foreach (['from', 'to'] as $key) {
- $language = $$key;
- $translator = Translator::get($language);
- $translations = $translator->getMessages();
-
- if (!isset($translations[$language])) {
- return $timeString;
- }
-
- $translationKey = $key.'Translations';
- $messages = $translations[$language];
- $months = $messages['months'];
- $weekdays = $messages['weekdays'];
- $meridiem = $messages['meridiem'] ?? ['AM', 'PM'];
-
- if ($key === 'from') {
- foreach (['months', 'weekdays'] as $variable) {
- $list = $messages[$variable.'_standalone'] ?? null;
-
- if ($list) {
- foreach ($$variable as $index => &$name) {
- $name .= '|'.$messages[$variable.'_standalone'][$index];
- }
- }
- }
- }
-
- $$translationKey = array_merge(
- $mode & CarbonInterface::TRANSLATE_MONTHS ? array_pad($months, 12, '>>DO NOT REPLACE<<') : [],
- $mode & CarbonInterface::TRANSLATE_MONTHS ? array_pad($messages['months_short'], 12, '>>DO NOT REPLACE<<') : [],
- $mode & CarbonInterface::TRANSLATE_DAYS ? array_pad($weekdays, 7, '>>DO NOT REPLACE<<') : [],
- $mode & CarbonInterface::TRANSLATE_DAYS ? array_pad($messages['weekdays_short'], 7, '>>DO NOT REPLACE<<') : [],
- $mode & CarbonInterface::TRANSLATE_UNITS ? array_map(function ($unit) use ($messages, $key, $cleanWord) {
- $parts = explode('|', $messages[$unit]);
-
- return $key === 'to'
- ? $cleanWord(end($parts))
- : '(?:'.implode('|', array_map($cleanWord, $parts)).')';
- }, [
- 'year',
- 'month',
- 'week',
- 'day',
- 'hour',
- 'minute',
- 'second',
- ]) : [],
- $mode & CarbonInterface::TRANSLATE_MERIDIEM ? array_map(function ($hour) use ($meridiem) {
- if (is_array($meridiem)) {
- return $meridiem[$hour < 12 ? 0 : 1];
- }
-
- return $meridiem($hour, 0, false);
- }, range(0, 23)) : []
- );
- }
-
- return substr(preg_replace_callback('/(?<=[\d\s+.\/,_-])('.implode('|', $fromTranslations).')(?=[\d\s+.\/,_-])/i', function ($match) use ($fromTranslations, $toTranslations) {
- [$chunk] = $match;
-
- foreach ($fromTranslations as $index => $word) {
- if (preg_match("/^$word\$/i", $chunk)) {
- return $toTranslations[$index] ?? '';
- }
- }
-
- return $chunk; // @codeCoverageIgnore
- }, " $timeString "), 1, -1);
- }
-
- /**
- * Translate a time string from the current locale (`$date->locale()`) to an other.
- *
- * @param string $timeString time string to translate
- * @param string|null $to output locale of the result returned ("en" by default)
- *
- * @return string
- */
- public function translateTimeStringTo($timeString, $to = null)
- {
- return static::translateTimeString($timeString, $this->getLocalTranslator()->getLocale(), $to);
- }
-
- /**
- * Get/set the locale for the current instance.
- *
- * @param string|null $locale
- * @param string[] ...$fallbackLocales
- *
- * @return $this|string
- */
- public function locale(string $locale = null, ...$fallbackLocales)
- {
- if ($locale === null) {
- return $this->getLocalTranslator()->getLocale();
- }
-
- if (!$this->localTranslator || $this->localTranslator->getLocale() !== $locale) {
- $translator = Translator::get($locale);
-
- if (!empty($fallbackLocales)) {
- $translator->setFallbackLocales($fallbackLocales);
-
- foreach ($fallbackLocales as $fallbackLocale) {
- $messages = Translator::get($fallbackLocale)->getMessages();
-
- if (isset($messages[$fallbackLocale])) {
- $translator->setMessages($fallbackLocale, $messages[$fallbackLocale]);
- }
- }
- }
-
- $this->setLocalTranslator($translator);
- }
-
- return $this;
- }
-
- /**
- * Get the current translator locale.
- *
- * @return string
- */
- public static function getLocale()
- {
- return static::translator()->getLocale();
- }
-
- /**
- * Set the current translator locale and indicate if the source locale file exists.
- * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function setLocale($locale)
- {
- return static::translator()->setLocale($locale) !== false;
- }
-
- /**
- * Set the fallback locale.
- *
- * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
- *
- * @param string $locale
- */
- public static function setFallbackLocale($locale)
- {
- $translator = static::getTranslator();
-
- if (method_exists($translator, 'setFallbackLocales')) {
- $translator->setFallbackLocales([$locale]);
-
- if ($translator instanceof Translator) {
- $preferredLocale = $translator->getLocale();
- $translator->setMessages($preferredLocale, array_replace_recursive(
- $translator->getMessages()[$locale] ?? [],
- Translator::get($locale)->getMessages()[$locale] ?? [],
- $translator->getMessages($preferredLocale)
- ));
- }
- }
- }
-
- /**
- * Get the fallback locale.
- *
- * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
- *
- * @return string|null
- */
- public static function getFallbackLocale()
- {
- $translator = static::getTranslator();
-
- if (method_exists($translator, 'getFallbackLocales')) {
- return $translator->getFallbackLocales()[0] ?? null;
- }
-
- return null;
- }
-
- /**
- * Set the current locale to the given, execute the passed function, reset the locale to previous one,
- * then return the result of the closure (or null if the closure was void).
- *
- * @param string $locale locale ex. en
- * @param callable $func
- *
- * @return mixed
- */
- public static function executeWithLocale($locale, $func)
- {
- $currentLocale = static::getLocale();
- $result = call_user_func($func, static::setLocale($locale) ? static::getLocale() : false, static::translator());
- static::setLocale($currentLocale);
-
- return $result;
- }
-
- /**
- * Returns true if the given locale is internally supported and has short-units support.
- * Support is considered enabled if either year, day or hour has a short variant translated.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasShortUnits($locale)
- {
- return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
- return $newLocale &&
- (
- ($y = static::translateWith($translator, 'y')) !== 'y' &&
- $y !== static::translateWith($translator, 'year')
- ) || (
- ($y = static::translateWith($translator, 'd')) !== 'd' &&
- $y !== static::translateWith($translator, 'day')
- ) || (
- ($y = static::translateWith($translator, 'h')) !== 'h' &&
- $y !== static::translateWith($translator, 'hour')
- );
- });
- }
-
- /**
- * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasDiffSyntax($locale)
- {
- return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
- if (!$newLocale) {
- return false;
- }
-
- foreach (['ago', 'from_now', 'before', 'after'] as $key) {
- if ($translator instanceof TranslatorBagInterface && $translator->getCatalogue($newLocale)->get($key) instanceof Closure) {
- continue;
- }
-
- if ($translator->trans($key) === $key) {
- return false;
- }
- }
-
- return true;
- });
- }
-
- /**
- * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
- * Support is considered enabled if the 3 words are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasDiffOneDayWords($locale)
- {
- return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
- return $newLocale &&
- $translator->trans('diff_now') !== 'diff_now' &&
- $translator->trans('diff_yesterday') !== 'diff_yesterday' &&
- $translator->trans('diff_tomorrow') !== 'diff_tomorrow';
- });
- }
-
- /**
- * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
- * Support is considered enabled if the 2 words are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasDiffTwoDayWords($locale)
- {
- return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
- return $newLocale &&
- $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' &&
- $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow';
- });
- }
-
- /**
- * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
- * Support is considered enabled if the 4 sentences are translated in the given locale.
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public static function localeHasPeriodSyntax($locale)
- {
- return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
- return $newLocale &&
- $translator->trans('period_recurrences') !== 'period_recurrences' &&
- $translator->trans('period_interval') !== 'period_interval' &&
- $translator->trans('period_start_date') !== 'period_start_date' &&
- $translator->trans('period_end_date') !== 'period_end_date';
- });
- }
-
- /**
- * Returns the list of internally available locales and already loaded custom locales.
- * (It will ignore custom translator dynamic loading.)
- *
- * @return array
- */
- public static function getAvailableLocales()
- {
- $translator = static::translator();
-
- return $translator instanceof Translator
- ? $translator->getAvailableLocales()
- : [$translator->getLocale()];
- }
-
- /**
- * Returns list of Language object for each available locale. This object allow you to get the ISO name, native
- * name, region and variant of the locale.
- *
- * @return Language[]
- */
- public static function getAvailableLocalesInfo()
- {
- $languages = [];
- foreach (static::getAvailableLocales() as $id) {
- $languages[$id] = new Language($id);
- }
-
- return $languages;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-/**
- * Trait Boundaries.
- *
- * startOf, endOf and derived method for each unit.
- *
- * Depends on the following properties:
- *
- * @property int $year
- * @property int $month
- * @property int $daysInMonth
- * @property int $quarter
- *
- * Depends on the following methods:
- *
- * @method $this setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0)
- * @method $this setDate(int $year, int $month, int $day)
- * @method $this addMonths(int $value = 1)
- */
-trait Macro
-{
- /**
- * The registered macros.
- *
- * @var array
- */
- protected static $globalMacros = [];
-
- /**
- * The registered generic macros.
- *
- * @var array
- */
- protected static $globalGenericMacros = [];
-
- /**
- * Register a custom macro.
- *
- * @example
- * ```
- * $userSettings = [
- * 'locale' => 'pt',
- * 'timezone' => 'America/Sao_Paulo',
- * ];
- * Carbon::macro('userFormat', function () use ($userSettings) {
- * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
- * });
- * echo Carbon::yesterday()->hours(11)->userFormat();
- * ```
- *
- * @param string $name
- * @param object|callable $macro
- *
- * @return void
- */
- public static function macro($name, $macro)
- {
- static::$globalMacros[$name] = $macro;
- }
-
- /**
- * Remove all macros and generic macros.
- */
- public static function resetMacros()
- {
- static::$globalMacros = [];
- static::$globalGenericMacros = [];
- }
-
- /**
- * Register a custom macro.
- *
- * @param object|callable $macro
- * @param int $priority marco with higher priority is tried first
- *
- * @return void
- */
- public static function genericMacro($macro, $priority = 0)
- {
- if (!isset(static::$globalGenericMacros[$priority])) {
- static::$globalGenericMacros[$priority] = [];
- krsort(static::$globalGenericMacros, SORT_NUMERIC);
- }
-
- static::$globalGenericMacros[$priority][] = $macro;
- }
-
- /**
- * Mix another object into the class.
- *
- * @example
- * ```
- * Carbon::mixin(new class {
- * public function addMoon() {
- * return function () {
- * return $this->addDays(30);
- * };
- * }
- * public function subMoon() {
- * return function () {
- * return $this->subDays(30);
- * };
- * }
- * });
- * $fullMoon = Carbon::create('2018-12-22');
- * $nextFullMoon = $fullMoon->addMoon();
- * $blackMoon = Carbon::create('2019-01-06');
- * $previousBlackMoon = $blackMoon->subMoon();
- * echo "$nextFullMoon\n";
- * echo "$previousBlackMoon\n";
- * ```
- *
- * @param object $mixin
- *
- * @throws \ReflectionException
- *
- * @return void
- */
- public static function mixin($mixin)
- {
- $methods = (new \ReflectionClass($mixin))->getMethods(
- \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED
- );
-
- foreach ($methods as $method) {
- if ($method->isConstructor() || $method->isDestructor()) {
- continue;
- }
- $method->setAccessible(true);
-
- static::macro($method->name, $method->invoke($mixin));
- }
- }
-
- /**
- * Checks if macro is registered.
- *
- * @param string $name
- *
- * @return bool
- */
- public static function hasMacro($name)
- {
- return isset(static::$globalMacros[$name]);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-
-/**
- * Trait Modifiers.
- *
- * Returns dates relative to current date using modifier short-hand.
- */
-trait Modifiers
-{
- /**
- * Midday/noon hour.
- *
- * @var int
- */
- protected static $midDayAt = 12;
-
- /**
- * get midday/noon hour
- *
- * @return int
- */
- public static function getMidDayAt()
- {
- return static::$midDayAt;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
- * hour, test it explicitly:
- * $date->format('G') == 13
- * or to set explicitly to a given hour:
- * $date->setTime(13, 0, 0, 0)
- *
- * Set midday/noon hour
- *
- * @param int $hour midday hour
- *
- * @return void
- */
- public static function setMidDayAt($hour)
- {
- static::$midDayAt = $hour;
- }
-
- /**
- * Modify to midday, default to self::$midDayAt
- *
- * @return static|CarbonInterface
- */
- public function midDay()
- {
- return $this->setTime(static::$midDayAt, 0, 0, 0);
- }
-
- /**
- * Modify to the next occurrence of a given day of the week.
- * If no dayOfWeek is provided, modify to the next occurrence
- * of the current day of the week. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function next($dayOfWeek = null)
- {
- if ($dayOfWeek === null) {
- $dayOfWeek = $this->dayOfWeek;
- }
-
- return $this->startOfDay()->modify('next '.static::$days[$dayOfWeek]);
- }
-
- /**
- * Go forward or backward to the next week- or weekend-day.
- *
- * @param bool $weekday
- * @param bool $forward
- *
- * @return static|CarbonInterface
- */
- private function nextOrPreviousDay($weekday = true, $forward = true)
- {
- /** @var CarbonInterface $step */
- $date = $this;
- $step = $forward ? 1 : -1;
-
- do {
- $date = $date->addDays($step);
- } while ($weekday ? $date->isWeekend() : $date->isWeekday());
-
- return $date;
- }
-
- /**
- * Go forward to the next weekday.
- *
- * @return static|CarbonInterface
- */
- public function nextWeekday()
- {
- return $this->nextOrPreviousDay();
- }
-
- /**
- * Go backward to the previous weekday.
- *
- * @return static|CarbonInterface
- */
- public function previousWeekday()
- {
- return $this->nextOrPreviousDay(true, false);
- }
-
- /**
- * Go forward to the next weekend day.
- *
- * @return static|CarbonInterface
- */
- public function nextWeekendDay()
- {
- return $this->nextOrPreviousDay(false);
- }
-
- /**
- * Go backward to the previous weekend day.
- *
- * @return static|CarbonInterface
- */
- public function previousWeekendDay()
- {
- return $this->nextOrPreviousDay(false, false);
- }
-
- /**
- * Modify to the previous occurrence of a given day of the week.
- * If no dayOfWeek is provided, modify to the previous occurrence
- * of the current day of the week. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function previous($dayOfWeek = null)
- {
- if ($dayOfWeek === null) {
- $dayOfWeek = $this->dayOfWeek;
- }
-
- return $this->startOfDay()->modify('last '.static::$days[$dayOfWeek]);
- }
-
- /**
- * Modify to the first occurrence of a given day of the week
- * in the current month. If no dayOfWeek is provided, modify to the
- * first day of the current month. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function firstOfMonth($dayOfWeek = null)
- {
- $date = $this->startOfDay();
-
- if ($dayOfWeek === null) {
- return $date->day(1);
- }
-
- return $date->modify('first '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year);
- }
-
- /**
- * Modify to the last occurrence of a given day of the week
- * in the current month. If no dayOfWeek is provided, modify to the
- * last day of the current month. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek
- *
- * @return static|CarbonInterface
- */
- public function lastOfMonth($dayOfWeek = null)
- {
- $date = $this->startOfDay();
-
- if ($dayOfWeek === null) {
- return $date->day($date->daysInMonth);
- }
-
- return $date->modify('last '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year);
- }
-
- /**
- * Modify to the given occurrence of a given day of the week
- * in the current month. If the calculated occurrence is outside the scope
- * of the current month, then return false and no modifications are made.
- * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int $nth
- * @param int $dayOfWeek
- *
- * @return mixed
- */
- public function nthOfMonth($nth, $dayOfWeek)
- {
- $date = $this->copy()->firstOfMonth();
- $check = $date->rawFormat('Y-m');
- $date = $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
-
- return $date->rawFormat('Y-m') === $check ? $this->modify("$date") : false;
- }
-
- /**
- * Modify to the first occurrence of a given day of the week
- * in the current quarter. If no dayOfWeek is provided, modify to the
- * first day of the current quarter. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function firstOfQuarter($dayOfWeek = null)
- {
- return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER - 2, 1)->firstOfMonth($dayOfWeek);
- }
-
- /**
- * Modify to the last occurrence of a given day of the week
- * in the current quarter. If no dayOfWeek is provided, modify to the
- * last day of the current quarter. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function lastOfQuarter($dayOfWeek = null)
- {
- return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER, 1)->lastOfMonth($dayOfWeek);
- }
-
- /**
- * Modify to the given occurrence of a given day of the week
- * in the current quarter. If the calculated occurrence is outside the scope
- * of the current quarter, then return false and no modifications are made.
- * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int $nth
- * @param int $dayOfWeek
- *
- * @return mixed
- */
- public function nthOfQuarter($nth, $dayOfWeek)
- {
- $date = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
- $lastMonth = $date->month;
- $year = $date->year;
- $date = $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
-
- return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify("$date");
- }
-
- /**
- * Modify to the first occurrence of a given day of the week
- * in the current year. If no dayOfWeek is provided, modify to the
- * first day of the current year. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function firstOfYear($dayOfWeek = null)
- {
- return $this->month(1)->firstOfMonth($dayOfWeek);
- }
-
- /**
- * Modify to the last occurrence of a given day of the week
- * in the current year. If no dayOfWeek is provided, modify to the
- * last day of the current year. Use the supplied constants
- * to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int|null $dayOfWeek day of the week default null
- *
- * @return static|CarbonInterface
- */
- public function lastOfYear($dayOfWeek = null)
- {
- return $this->month(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek);
- }
-
- /**
- * Modify to the given occurrence of a given day of the week
- * in the current year. If the calculated occurrence is outside the scope
- * of the current year, then return false and no modifications are made.
- * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
- *
- * @param int $nth
- * @param int $dayOfWeek
- *
- * @return mixed
- */
- public function nthOfYear($nth, $dayOfWeek)
- {
- $date = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
-
- return $this->year === $date->year ? $this->modify("$date") : false;
- }
-
- /**
- * Modify the current instance to the average of a given instance (default now) and the current instance
- * (second-precision).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|null $date
- *
- * @return static|CarbonInterface
- */
- public function average($date = null)
- {
- return $this->addRealMicroseconds((int) ($this->diffInRealMicroseconds($this->resolveCarbon($date), false) / 2));
- }
-
- /**
- * Get the closest date from the instance (second-precision).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- *
- * @return static|CarbonInterface
- */
- public function closest($date1, $date2)
- {
- return $this->diffInRealMicroseconds($date1) < $this->diffInRealMicroseconds($date2) ? $date1 : $date2;
- }
-
- /**
- * Get the farthest date from the instance (second-precision).
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
- *
- * @return static|CarbonInterface
- */
- public function farthest($date1, $date2)
- {
- return $this->diffInRealMicroseconds($date1) > $this->diffInRealMicroseconds($date2) ? $date1 : $date2;
- }
-
- /**
- * Get the minimum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return static|CarbonInterface
- */
- public function min($date = null)
- {
- $date = $this->resolveCarbon($date);
-
- return $this->lt($date) ? $this : $date;
- }
-
- /**
- * Get the minimum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see min()
- *
- * @return static|CarbonInterface
- */
- public function minimum($date = null)
- {
- return $this->min($date);
- }
-
- /**
- * Get the maximum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @return static|CarbonInterface
- */
- public function max($date = null)
- {
- $date = $this->resolveCarbon($date);
-
- return $this->gt($date) ? $this : $date;
- }
-
- /**
- * Get the maximum instance between a given instance (default now) and the current instance.
- *
- * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
- *
- * @see max()
- *
- * @return static|CarbonInterface
- */
- public function maximum($date = null)
- {
- return $this->max($date);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\Carbon;
-use Carbon\CarbonImmutable;
-
-/**
- * Trait Mutability.
- *
- * Utils to know if the current object is mutable or immutable and convert it.
- */
-trait Mutability
-{
- /**
- * Returns true if the current class/instance is mutable.
- *
- * @return bool
- */
- public static function isMutable()
- {
- return false;
- }
-
- /**
- * Returns true if the current class/instance is immutable.
- *
- * @return bool
- */
- public static function isImmutable()
- {
- return !static::isMutable();
- }
-
- /**
- * Cast the current instance into the given class.
- *
- * @param string $className The $className::instance() method will be called to cast the current object.
- *
- * @return object
- */
- public function cast(string $className)
- {
- if (!method_exists($className, 'instance')) {
- throw new \InvalidArgumentException("$className has not the instance() method needed to cast the date.");
- }
-
- return $className::instance($this);
- }
-
- /**
- * Return a mutable copy of the instance.
- *
- * @return Carbon
- */
- public function toMutable()
- {
- /** @var Carbon $date */
- $date = $this->cast(Carbon::class);
-
- return $date;
- }
-
- /**
- * Return a immutable copy of the instance.
- *
- * @return CarbonImmutable
- */
- public function toImmutable()
- {
- /** @var CarbonImmutable $date */
- $date = $this->cast(CarbonImmutable::class);
-
- return $date;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-
-/**
- * Trait Options.
- *
- * Embed base methods to change settings of Carbon classes.
- *
- * Depends on the following methods:
- *
- * @method \Carbon\Carbon|\Carbon\CarbonImmutable shiftTimezone($timezone) Set the timezone
- */
-trait Options
-{
- use Localization;
-
- /**
- * Customizable PHP_INT_SIZE override.
- *
- * @var int
- */
- public static $PHPIntSize = PHP_INT_SIZE;
-
- /**
- * First day of week.
- *
- * @var int
- */
- protected static $weekStartsAt = CarbonInterface::MONDAY;
-
- /**
- * Last day of week.
- *
- * @var int
- */
- protected static $weekEndsAt = CarbonInterface::SUNDAY;
-
- /**
- * Days of weekend.
- *
- * @var array
- */
- protected static $weekendDays = [
- CarbonInterface::SATURDAY,
- CarbonInterface::SUNDAY,
- ];
-
- /**
- * Format regex patterns.
- *
- * @var array
- */
- protected static $regexFormats = [
- 'd' => '(3[01]|[12][0-9]|0[1-9])',
- 'D' => '([a-zA-Z]{3})',
- 'j' => '([123][0-9]|[1-9])',
- 'l' => '([a-zA-Z]{2,})',
- 'N' => '([1-7])',
- 'S' => '([a-zA-Z]{2})',
- 'w' => '([0-6])',
- 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])',
- 'W' => '(5[012]|[1-4][0-9]|[1-9])',
- 'F' => '([a-zA-Z]{2,})',
- 'm' => '(1[012]|0[1-9])',
- 'M' => '([a-zA-Z]{3})',
- 'n' => '(1[012]|[1-9])',
- 't' => '(2[89]|3[01])',
- 'L' => '(0|1)',
- 'o' => '([1-9][0-9]{0,4})',
- 'Y' => '([1-9]?[0-9]{4})',
- 'y' => '([0-9]{2})',
- 'a' => '(am|pm)',
- 'A' => '(AM|PM)',
- 'B' => '([0-9]{3})',
- 'g' => '(1[012]|[1-9])',
- 'G' => '(2[0-3]|1?[0-9])',
- 'h' => '(1[012]|0[1-9])',
- 'H' => '(2[0-3]|[01][0-9])',
- 'i' => '([0-5][0-9])',
- 's' => '([0-5][0-9])',
- 'u' => '([0-9]{1,6})',
- 'v' => '([0-9]{1,3})',
- 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\/[a-zA-Z]*)',
- 'I' => '(0|1)',
- 'O' => '([\+\-](1[012]|0[0-9])[0134][05])',
- 'P' => '([\+\-](1[012]|0[0-9]):[0134][05])',
- 'T' => '([a-zA-Z]{1,5})',
- 'Z' => '(-?[1-5]?[0-9]{1,4})',
- 'U' => '([0-9]*)',
-
- // The formats below are combinations of the above formats.
- 'c' => '(([1-9]?[0-9]{4})\-(1[012]|0[1-9])\-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[\+\-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP
- 'r' => '(([a-zA-Z]{3}), ([123][0-9]|[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [\+\-](1[012]|0[0-9])([0134][05]))', // D, j M Y H:i:s O
- ];
-
- /**
- * Indicates if months should be calculated with overflow.
- * Global setting.
- *
- * @var bool
- */
- protected static $monthsOverflow = true;
-
- /**
- * Indicates if years should be calculated with overflow.
- * Global setting.
- *
- * @var bool
- */
- protected static $yearsOverflow = true;
-
- /**
- * Indicates if the strict mode is in use.
- * Global setting.
- *
- * @var bool
- */
- protected static $strictModeEnabled = true;
-
- /**
- * Function to call instead of format.
- *
- * @var string|callable|null
- */
- protected static $formatFunction = null;
-
- /**
- * Function to call instead of createFromFormat.
- *
- * @var string|callable|null
- */
- protected static $createFromFormatFunction = null;
-
- /**
- * Function to call instead of parse.
- *
- * @var string|callable|null
- */
- protected static $parseFunction = null;
-
- /**
- * Indicates if months should be calculated with overflow.
- * Specific setting.
- *
- * @var bool|null
- */
- protected $localMonthsOverflow = null;
-
- /**
- * Indicates if years should be calculated with overflow.
- * Specific setting.
- *
- * @var bool|null
- */
- protected $localYearsOverflow = null;
-
- /**
- * Indicates if the strict mode is in use.
- * Specific setting.
- *
- * @var bool|null
- */
- protected $localStrictModeEnabled = null;
-
- /**
- * Options for diffForHumans and forHumans methods.
- *
- * @var bool|null
- */
- protected $localHumanDiffOptions = null;
-
- /**
- * Format to use on string cast.
- *
- * @var string|null
- */
- protected $localToStringFormat = null;
-
- /**
- * Format to use on JSON serialization.
- *
- * @var string|null
- */
- protected $localSerializer = null;
-
- /**
- * Instance-specific macros.
- *
- * @var array|null
- */
- protected $localMacros = null;
-
- /**
- * Instance-specific generic macros.
- *
- * @var array|null
- */
- protected $localGenericMacros = null;
-
- /**
- * Function to call instead of format.
- *
- * @var string|callable|null
- */
- protected $localFormatFunction = null;
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * @see settings
- *
- * Enable the strict mode (or disable with passing false).
- *
- * @param bool $strictModeEnabled
- */
- public static function useStrictMode($strictModeEnabled = true)
- {
- static::$strictModeEnabled = $strictModeEnabled;
- }
-
- /**
- * Returns true if the strict mode is globally in use, false else.
- * (It can be overridden in specific instances.)
- *
- * @return bool
- */
- public static function isStrictModeEnabled()
- {
- return static::$strictModeEnabled;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Indicates if months should be calculated with overflow.
- *
- * @param bool $monthsOverflow
- *
- * @return void
- */
- public static function useMonthsOverflow($monthsOverflow = true)
- {
- static::$monthsOverflow = $monthsOverflow;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Reset the month overflow behavior.
- *
- * @return void
- */
- public static function resetMonthsOverflow()
- {
- static::$monthsOverflow = true;
- }
-
- /**
- * Get the month overflow global behavior (can be overridden in specific instances).
- *
- * @return bool
- */
- public static function shouldOverflowMonths()
- {
- return static::$monthsOverflow;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Indicates if years should be calculated with overflow.
- *
- * @param bool $yearsOverflow
- *
- * @return void
- */
- public static function useYearsOverflow($yearsOverflow = true)
- {
- static::$yearsOverflow = $yearsOverflow;
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather use the ->settings() method.
- * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
- * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @see settings
- *
- * Reset the month overflow behavior.
- *
- * @return void
- */
- public static function resetYearsOverflow()
- {
- static::$yearsOverflow = true;
- }
-
- /**
- * Get the month overflow global behavior (can be overridden in specific instances).
- *
- * @return bool
- */
- public static function shouldOverflowYears()
- {
- return static::$yearsOverflow;
- }
-
- /**
- * Set specific options.
- * - strictMode: true|false|null
- * - monthOverflow: true|false|null
- * - yearOverflow: true|false|null
- * - humanDiffOptions: int|null
- * - toStringFormat: string|Closure|null
- * - toJsonFormat: string|Closure|null
- * - locale: string|null
- * - timezone: \DateTimeZone|string|int|null
- * - macros: array|null
- * - genericMacros: array|null
- *
- * @param array $settings
- *
- * @return $this
- */
- public function settings(array $settings)
- {
- $this->localStrictModeEnabled = $settings['strictMode'] ?? null;
- $this->localMonthsOverflow = $settings['monthOverflow'] ?? null;
- $this->localYearsOverflow = $settings['yearOverflow'] ?? null;
- $this->localHumanDiffOptions = $settings['humanDiffOptions'] ?? null;
- $this->localToStringFormat = $settings['toStringFormat'] ?? null;
- $this->localSerializer = $settings['toJsonFormat'] ?? null;
- $this->localMacros = $settings['macros'] ?? null;
- $this->localGenericMacros = $settings['genericMacros'] ?? null;
- $this->localFormatFunction = $settings['formatFunction'] ?? null;
- $date = $this;
- if (isset($settings['locale'])) {
- $locales = $settings['locale'];
-
- if (!is_array($locales)) {
- $locales = [$locales];
- }
-
- $date = $date->locale(...$locales);
- }
- if (isset($settings['timezone'])) {
- $date = $date->shiftTimezone($settings['timezone']);
- }
-
- return $date;
- }
-
- /**
- * Returns current local settings.
- *
- * @return array
- */
- public function getSettings()
- {
- $settings = [];
- $map = [
- 'localStrictModeEnabled' => 'strictMode',
- 'localMonthsOverflow' => 'monthOverflow',
- 'localYearsOverflow' => 'yearOverflow',
- 'localHumanDiffOptions' => 'humanDiffOptions',
- 'localToStringFormat' => 'toStringFormat',
- 'localSerializer' => 'toJsonFormat',
- 'localMacros' => 'macros',
- 'localGenericMacros' => 'genericMacros',
- 'locale' => 'locale',
- 'tzName' => 'timezone',
- 'localFormatFunction' => 'formatFunction',
- ];
- foreach ($map as $property => $key) {
- $value = $this->$property ?? null;
- if ($value !== null) {
- $settings[$key] = $value;
- }
- }
-
- return $settings;
- }
-
- /**
- * Show truthy properties on var_dump().
- *
- * @return array
- */
- public function __debugInfo()
- {
- return array_filter(get_object_vars($this), function ($var) {
- return $var;
- });
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-use InvalidArgumentException;
-
-/**
- * Trait Rounding.
- *
- * Round, ceil, floor units.
- *
- * Depends on the following methods:
- *
- * @method CarbonInterface copy()
- * @method CarbonInterface startOfWeek()
- */
-trait Rounding
-{
- /**
- * Round the current instance at the given unit with given precision if specified and the given function.
- *
- * @param string $unit
- * @param float|int $precision
- * @param string $function
- *
- * @return CarbonInterface
- */
- public function roundUnit($unit, $precision = 1, $function = 'round')
- {
- $metaUnits = [
- // @call roundUnit
- 'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'],
- // @call roundUnit
- 'century' => [static::YEARS_PER_CENTURY, 'year'],
- // @call roundUnit
- 'decade' => [static::YEARS_PER_DECADE, 'year'],
- // @call roundUnit
- 'quarter' => [static::MONTHS_PER_QUARTER, 'month'],
- // @call roundUnit
- 'millisecond' => [1000, 'microsecond'],
- ];
- $normalizedUnit = static::singularUnit($unit);
- $ranges = array_merge(static::getRangesByUnit(), [
- // @call roundUnit
- 'microsecond' => [0, 999999],
- ]);
- $factor = 1;
- if (isset($metaUnits[$normalizedUnit])) {
- [$factor, $normalizedUnit] = $metaUnits[$normalizedUnit];
- }
- $precision *= $factor;
-
- if (!isset($ranges[$normalizedUnit])) {
- throw new InvalidArgumentException("Unknown unit '$unit' to floor");
- }
-
- $found = false;
- $fraction = 0;
- $arguments = null;
- $factor = $this->year < 0 ? -1 : 1;
- $changes = [];
-
- foreach ($ranges as $unit => [$minimum, $maximum]) {
- if ($normalizedUnit === $unit) {
- $arguments = [$this->$unit, $minimum];
- $fraction = $precision - floor($precision);
- $found = true;
-
- continue;
- }
-
- if ($found) {
- $delta = $maximum + 1 - $minimum;
- $factor /= $delta;
- $fraction *= $delta;
- $arguments[0] += $this->$unit * $factor;
- $changes[$unit] = round($minimum + ($fraction ? $fraction * call_user_func($function, ($this->$unit - $minimum) / $fraction) : 0));
- // Cannot use modulo as it lose double precision
- while ($changes[$unit] >= $delta) {
- $changes[$unit] -= $delta;
- }
- $fraction -= floor($fraction);
- }
- }
-
- [$value, $minimum] = $arguments;
- /** @var CarbonInterface $result */
- $result = $this->$normalizedUnit(floor(call_user_func($function, ($value - $minimum) / $precision) * $precision + $minimum));
- foreach ($changes as $unit => $value) {
- $result = $result->$unit($value);
- }
-
- return $result;
- }
-
- /**
- * Truncate the current instance at the given unit with given precision if specified.
- *
- * @param string $unit
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function floorUnit($unit, $precision = 1)
- {
- return $this->roundUnit($unit, $precision, 'floor');
- }
-
- /**
- * Ceil the current instance at the given unit with given precision if specified.
- *
- * @param string $unit
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function ceilUnit($unit, $precision = 1)
- {
- return $this->roundUnit($unit, $precision, 'ceil');
- }
-
- /**
- * Round the current instance second with given precision if specified.
- *
- * @param float|int $precision
- * @param string $function
- *
- * @return CarbonInterface
- */
- public function round($precision = 1, $function = 'round')
- {
- return $this->roundUnit('second', $precision, $function);
- }
-
- /**
- * Round the current instance second with given precision if specified.
- *
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function floor($precision = 1)
- {
- return $this->roundUnit('second', $precision, 'floor');
- }
-
- /**
- * Ceil the current instance second with given precision if specified.
- *
- * @param float|int $precision
- *
- * @return CarbonInterface
- */
- public function ceil($precision = 1)
- {
- return $this->roundUnit('second', $precision, 'ceil');
- }
-
- /**
- * Round the current instance week.
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return CarbonInterface
- */
- public function roundWeek($weekStartsAt = null)
- {
- return $this->closest($this->copy()->floorWeek($weekStartsAt), $this->copy()->ceilWeek($weekStartsAt));
- }
-
- /**
- * Truncate the current instance week.
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return CarbonInterface
- */
- public function floorWeek($weekStartsAt = null)
- {
- return $this->startOfWeek($weekStartsAt);
- }
-
- /**
- * Ceil the current instance week.
- *
- * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
- *
- * @return CarbonInterface
- */
- public function ceilWeek($weekStartsAt = null)
- {
- if ($this->isMutable()) {
- $startOfWeek = $this->copy()->startOfWeek($weekStartsAt);
-
- return $startOfWeek != $this ?
- $this->startOfWeek($weekStartsAt)->addWeek() :
- $this;
- }
-
- $startOfWeek = $this->startOfWeek($weekStartsAt);
-
- return $startOfWeek != $this ?
- $startOfWeek->addWeek() :
- $this->copy();
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-use InvalidArgumentException;
-
-/**
- * Trait Serialization.
- *
- * Serialization and JSON stuff.
- *
- * Depends on the following properties:
- *
- * @property int $year
- * @property int $month
- * @property int $daysInMonth
- * @property int $quarter
- *
- * Depends on the following methods:
- *
- * @method string|static locale(string $locale = null)
- * @method string toJSON()
- */
-trait Serialization
-{
- /**
- * The custom Carbon JSON serializer.
- *
- * @var callable|null
- */
- protected static $serializer;
-
- /**
- * Locale to dump comes here before serialization.
- *
- * @var string|null
- */
- protected $dumpLocale = null;
-
- /**
- * Return a serialized string of the instance.
- *
- * @return string
- */
- public function serialize()
- {
- return serialize($this);
- }
-
- /**
- * Create an instance from a serialized string.
- *
- * @param string $value
- *
- * @throws \InvalidArgumentException
- *
- * @return static|CarbonInterface
- */
- public static function fromSerialized($value)
- {
- $instance = @unserialize("$value");
-
- if (!$instance instanceof static) {
- throw new InvalidArgumentException('Invalid serialized value.');
- }
-
- return $instance;
- }
-
- /**
- * The __set_state handler.
- *
- * @param string|array $dump
- *
- * @return static|CarbonInterface
- */
- public static function __set_state($dump)
- {
- if (is_string($dump)) {
- return static::parse($dump);
- }
-
- /** @var \DateTimeInterface $date */
- $date = get_parent_class(static::class) && method_exists(parent::class, '__set_state')
- ? parent::__set_state($dump)
- : (object) $dump;
-
- return static::instance($date);
- }
-
- /**
- * Returns the list of properties to dump on serialize() called on.
- *
- * @return array
- */
- public function __sleep()
- {
- $properties = ['date', 'timezone_type', 'timezone'];
- if ($this->localTranslator ?? null) {
- $properties[] = 'dumpLocale';
- $this->dumpLocale = $this->locale ?? null;
- }
-
- return $properties;
- }
-
- /**
- * Set locale if specified on unserialize() called.
- */
- public function __wakeup()
- {
- if (get_parent_class() && method_exists(parent::class, '__wakeup')) {
- parent::__wakeup();
- }
- if (isset($this->dumpLocale)) {
- $this->locale($this->dumpLocale);
- $this->dumpLocale = null;
- }
- }
-
- /**
- * Prepare the object for JSON serialization.
- *
- * @return array|string
- */
- public function jsonSerialize()
- {
- $serializer = $this->localSerializer ?? static::$serializer;
- if ($serializer) {
- return is_string($serializer)
- ? $this->rawFormat($serializer)
- : call_user_func($serializer, $this);
- }
-
- return $this->toJSON();
- }
-
- /**
- * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
- * You should rather transform Carbon object before the serialization.
- *
- * JSON serialize all Carbon instances using the given callback.
- *
- * @param callable $callback
- *
- * @return void
- */
- public static function serializeUsing($callback)
- {
- static::$serializer = $callback;
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-
-trait Test
-{
- ///////////////////////////////////////////////////////////////////
- ///////////////////////// TESTING AIDS ////////////////////////////
- ///////////////////////////////////////////////////////////////////
-
- /**
- * A test Carbon instance to be returned when now instances are created.
- *
- * @var static|CarbonInterface
- */
- protected static $testNow;
-
- /**
- * Set a Carbon instance (real or mock) to be returned when a "now"
- * instance is created. The provided instance will be returned
- * specifically under the following conditions:
- * - A call to the static now() method, ex. Carbon::now()
- * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
- * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
- * - When a string containing the desired time is passed to Carbon::parse().
- *
- * Note the timezone parameter was left out of the examples above and
- * has no affect as the mock value will be returned regardless of its value.
- *
- * To clear the test instance call this method using the default
- * parameter of null.
- *
- * /!\ Use this method for unit tests only.
- *
- * @param CarbonInterface|string|null $testNow real or mock Carbon instance
- */
- public static function setTestNow($testNow = null)
- {
- static::$testNow = is_string($testNow) ? static::parse($testNow) : $testNow;
- }
-
- /**
- * Get the Carbon instance (real or mock) to be returned when a "now"
- * instance is created.
- *
- * @return static|CarbonInterface the current instance used for testing
- */
- public static function getTestNow()
- {
- return static::$testNow;
- }
-
- /**
- * Determine if there is a valid test instance set. A valid test instance
- * is anything that is not null.
- *
- * @return bool true if there is a test instance, otherwise false
- */
- public static function hasTestNow()
- {
- return static::getTestNow() !== null;
- }
-
- protected static function mockConstructorParameters(&$time, &$tz)
- {
- /** @var \Carbon\CarbonImmutable|\Carbon\Carbon $testInstance */
- $testInstance = clone static::getTestNow();
-
- //shift the time according to the given time zone
- if ($tz !== null && $tz !== static::getTestNow()->getTimezone()) {
- $testInstance = $testInstance->setTimezone($tz);
- } else {
- $tz = $testInstance->getTimezone();
- }
-
- if (static::hasRelativeKeywords($time)) {
- $testInstance = $testInstance->modify($time);
- }
-
- $time = $testInstance instanceof self ? $testInstance->rawFormat(static::MOCK_DATETIME_FORMAT) : $testInstance->format(static::MOCK_DATETIME_FORMAT);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-
-/**
- * Trait Timestamp.
- */
-trait Timestamp
-{
- /**
- * Create a Carbon instance from a timestamp.
- *
- * @param int $timestamp
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimestamp($timestamp, $tz = null)
- {
- return static::today($tz)->setTimestamp((int) $timestamp);
- }
-
- /**
- * Create a Carbon instance from a timestamp in milliseconds.
- *
- * @param int $timestamp
- * @param \DateTimeZone|string|null $tz
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimestampMs($timestamp, $tz = null)
- {
- return static::rawCreateFromFormat('U.u', sprintf('%F', $timestamp / 1000))
- ->setTimezone($tz);
- }
-
- /**
- * Create a Carbon instance from an UTC timestamp.
- *
- * @param int $timestamp
- *
- * @return static|CarbonInterface
- */
- public static function createFromTimestampUTC($timestamp)
- {
- return new static('@'.$timestamp);
- }
-
- /**
- * Set the instance's timestamp.
- *
- * @param int $value
- *
- * @return static|CarbonInterface
- */
- public function timestamp($value)
- {
- return $this->setTimestamp((int) $value);
- }
-
- /**
- * Returns a timestamp rounded with the given precision (6 by default).
- *
- * @example getPreciseTimestamp() 1532087464437474 (microsecond maximum precision)
- * @example getPreciseTimestamp(6) 1532087464437474
- * @example getPreciseTimestamp(5) 153208746443747 (1/100000 second precision)
- * @example getPreciseTimestamp(4) 15320874644375 (1/10000 second precision)
- * @example getPreciseTimestamp(3) 1532087464437 (millisecond precision)
- * @example getPreciseTimestamp(2) 153208746444 (1/100 second precision)
- * @example getPreciseTimestamp(1) 15320874644 (1/10 second precision)
- * @example getPreciseTimestamp(0) 1532087464 (second precision)
- * @example getPreciseTimestamp(-1) 153208746 (10 second precision)
- * @example getPreciseTimestamp(-2) 15320875 (100 second precision)
- *
- * @param int $precision
- *
- * @return float
- */
- public function getPreciseTimestamp($precision = 6)
- {
- return round($this->rawFormat('Uu') / pow(10, 6 - $precision));
- }
-
- /**
- * Returns the milliseconds timestamps used amongst other by Date javascript objects.
- *
- * @return float
- */
- public function valueOf()
- {
- return $this->getPreciseTimestamp(3);
- }
-
- /**
- * @alias getTimestamp
- *
- * Returns the UNIX timestamp for the current date.
- *
- * @return int
- */
- public function unix()
- {
- return $this->getTimestamp();
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-use Carbon\CarbonInterval;
-use DateInterval;
-use InvalidArgumentException;
-
-/**
- * Trait Units.
- *
- * Add, subtract and set units.
- */
-trait Units
-{
- /**
- * Add seconds to the instance using timestamp. Positive $value travels
- * forward while negative $value travels into the past.
- *
- * @param string $unit
- * @param int $value
- *
- * @return static
- */
- public function addRealUnit($unit, $value = 1)
- {
- switch ($unit) {
- // @call addRealUnit
- case 'micro':
- // @call addRealUnit
- case 'microsecond':
- /* @var CarbonInterface $this */
- $diff = $this->microsecond + $value;
- $time = $this->getTimestamp();
- $seconds = (int) floor($diff / static::MICROSECONDS_PER_SECOND);
- $time += $seconds;
- $diff -= $seconds * static::MICROSECONDS_PER_SECOND;
- $microtime = str_pad("$diff", 6, '0', STR_PAD_LEFT);
- $tz = $this->tz;
-
- return $this->tz('UTC')->modify("@$time.$microtime")->tz($tz);
- // @call addRealUnit
- case 'milli':
- // @call addRealUnit
- case 'millisecond':
- return $this->addRealUnit('microsecond', $value * static::MICROSECONDS_PER_MILLISECOND);
- break;
- // @call addRealUnit
- case 'second':
- break;
- // @call addRealUnit
- case 'minute':
- $value *= static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'hour':
- $value *= static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'day':
- $value *= static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'week':
- $value *= static::DAYS_PER_WEEK * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'month':
- $value *= 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'quarter':
- $value *= static::MONTHS_PER_QUARTER * 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'year':
- $value *= 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'decade':
- $value *= static::YEARS_PER_DECADE * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'century':
- $value *= static::YEARS_PER_CENTURY * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- // @call addRealUnit
- case 'millennium':
- $value *= static::YEARS_PER_MILLENNIUM * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
- break;
- default:
- if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
- throw new InvalidArgumentException("Invalid unit for real timestamp add/sub: '$unit'");
- }
-
- return $this;
- }
-
- /* @var CarbonInterface $this */
- return $this->setTimestamp((int) ($this->getTimestamp() + $value));
- }
-
- public function subRealUnit($unit, $value = 1)
- {
- return $this->addRealUnit($unit, -$value);
- }
-
- /**
- * Returns true if a property can be changed via setter.
- *
- * @param string $unit
- *
- * @return bool
- */
- public static function isModifiableUnit($unit)
- {
- static $modifiableUnits = [
- // @call addUnit
- 'millennium',
- // @call addUnit
- 'century',
- // @call addUnit
- 'decade',
- // @call addUnit
- 'quarter',
- // @call addUnit
- 'week',
- // @call addUnit
- 'weekday',
- ];
-
- return in_array($unit, $modifiableUnits) || in_array($unit, static::$units);
- }
-
- /**
- * Add given units or interval to the current instance.
- *
- * @example $date->add('hour', 3)
- * @example $date->add(15, 'days')
- * @example $date->add(CarbonInterval::days(4))
- *
- * @param string|DateInterval $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function add($unit, $value = 1, $overflow = null)
- {
- if (is_string($unit) && func_num_args() === 1) {
- $unit = CarbonInterval::make($unit);
- }
-
- if ($unit instanceof DateInterval) {
- return parent::add($unit);
- }
-
- if (is_numeric($unit)) {
- $tempUnit = $value;
- $value = $unit;
- $unit = $tempUnit;
- }
-
- return $this->addUnit($unit, $value, $overflow);
- }
-
- /**
- * Add given units to the current instance.
- *
- * @param string $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function addUnit($unit, $value = 1, $overflow = null)
- {
- /** @var CarbonInterface $date */
- $date = $this;
-
- if (!is_numeric($value) || !floatval($value)) {
- return $date->isMutable() ? $date : $date->copy();
- }
-
- $metaUnits = [
- 'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'],
- 'century' => [static::YEARS_PER_CENTURY, 'year'],
- 'decade' => [static::YEARS_PER_DECADE, 'year'],
- 'quarter' => [static::MONTHS_PER_QUARTER, 'month'],
- ];
- if (isset($metaUnits[$unit])) {
- [$factor, $unit] = $metaUnits[$unit];
- $value *= $factor;
- }
-
- if ($unit === 'weekday') {
- $weekendDays = static::getWeekendDays();
- if ($weekendDays !== [static::SATURDAY, static::SUNDAY]) {
- $absoluteValue = abs($value);
- $sign = $value / max(1, $absoluteValue);
- $weekDaysCount = 7 - min(6, count(array_unique($weekendDays)));
- $weeks = floor($absoluteValue / $weekDaysCount);
- for ($diff = $absoluteValue % $weekDaysCount; $diff; $diff--) {
- $date = $date->addDays($sign);
- while (in_array($date->dayOfWeek, $weekendDays)) {
- $date = $date->addDays($sign);
- }
- }
-
- $value = $weeks * $sign;
- $unit = 'week';
- }
-
- $timeString = $date->toTimeString();
- } elseif ($canOverflow = in_array($unit, [
- 'month',
- 'year',
- ]) && ($overflow === false || (
- $overflow === null &&
- ($ucUnit = ucfirst($unit).'s') &&
- !($this->{'local'.$ucUnit.'Overflow'} ?? static::{'shouldOverflow'.$ucUnit}())
- ))) {
- $day = $date->day;
- }
-
- $value = (int) $value;
-
- if ($unit === 'milli' || $unit === 'millisecond') {
- $unit = 'microsecond';
- $value *= static::MICROSECONDS_PER_MILLISECOND;
- }
-
- // Work-around for bug https://bugs.php.net/bug.php?id=75642
- if ($unit === 'micro' || $unit === 'microsecond') {
- $microseconds = $this->micro + $value;
- $second = (int) floor($microseconds / static::MICROSECONDS_PER_SECOND);
- $microseconds %= static::MICROSECONDS_PER_SECOND;
- if ($microseconds < 0) {
- $microseconds += static::MICROSECONDS_PER_SECOND;
- }
- $date = $date->microseconds($microseconds);
- $unit = 'second';
- $value = $second;
- }
- $date = $date->modify("$value $unit");
-
- if (isset($timeString)) {
- return $date->setTimeFromTimeString($timeString);
- }
-
- if (isset($canOverflow, $day) && $canOverflow && $day !== $date->day) {
- $date = $date->modify('last day of previous month');
- }
-
- return $date;
- }
-
- /**
- * Subtract given units to the current instance.
- *
- * @param string $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function subUnit($unit, $value = 1, $overflow = null)
- {
- return $this->addUnit($unit, -$value, $overflow);
- }
-
- /**
- * Subtract given units or interval to the current instance.
- *
- * @example $date->sub('hour', 3)
- * @example $date->sub(15, 'days')
- * @example $date->sub(CarbonInterval::days(4))
- *
- * @param string|DateInterval $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function sub($unit, $value = 1, $overflow = null)
- {
- if (is_string($unit) && func_num_args() === 1) {
- $unit = CarbonInterval::make($unit);
- }
-
- if ($unit instanceof DateInterval) {
- return parent::sub($unit);
- }
-
- if (is_numeric($unit)) {
- $_unit = $value;
- $value = $unit;
- $unit = $_unit;
- unset($_unit);
- }
-
- return $this->addUnit($unit, -floatval($value), $overflow);
- }
-
- /**
- * Subtract given units or interval to the current instance.
- *
- * @see sub()
- *
- * @param string|DateInterval $unit
- * @param int $value
- * @param bool|null $overflow
- *
- * @return CarbonInterface
- */
- public function subtract($unit, $value = 1, $overflow = null)
- {
- if (is_string($unit) && func_num_args() === 1) {
- $unit = CarbonInterval::make($unit);
- }
-
- return $this->sub($unit, $value, $overflow);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon\Traits;
-
-use Carbon\CarbonInterface;
-
-/**
- * Trait Week.
- *
- * week and ISO week number, year and count in year.
- *
- * Depends on the following properties:
- *
- * @property int $daysInYear
- * @property int $dayOfWeek
- * @property int $dayOfYear
- * @property int $year
- *
- * Depends on the following methods:
- *
- * @method CarbonInterface|static addWeeks(int $weeks = 1)
- * @method CarbonInterface|static copy()
- * @method CarbonInterface|static dayOfYear(int $dayOfYear)
- * @method string getTranslationMessage(string $key)
- * @method CarbonInterface|static next(int $day)
- * @method CarbonInterface|static startOfWeek(int $day = 1)
- * @method CarbonInterface|static subWeeks(int $weeks = 1)
- * @method CarbonInterface|static year(int $year = null)
- */
-trait Week
-{
- /**
- * Set/get the week number of year using given first day of week and first
- * day of year included in the first week. Or use ISO format if no settings
- * given.
- *
- * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int|static
- */
- public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
- {
- return $this->weekYear(
- $year,
- $dayOfWeek ?? 1,
- $dayOfYear ?? 4
- );
- }
-
- /**
- * Set/get the week number of year using given first day of week and first
- * day of year included in the first week. Or use US format if no settings
- * given (Sunday / Jan 6).
- *
- * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int|static|CarbonInterface
- */
- public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
- {
- $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
- $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
-
- if ($year !== null) {
- $year = (int) round($year);
-
- if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) {
- return $this->copy();
- }
-
- $week = $this->week(null, $dayOfWeek, $dayOfYear);
- $day = $this->dayOfWeek;
- $date = $this->year($year);
- switch ($date->weekYear(null, $dayOfWeek, $dayOfYear) - $year) {
- case 1:
- $date = $date->subWeeks(26);
- break;
- case -1:
- $date = $date->addWeeks(26);
- break;
- }
-
- $date = $date->addWeeks($week - $date->week(null, $dayOfWeek, $dayOfYear))->startOfWeek($dayOfWeek);
-
- if ($date->dayOfWeek === $day) {
- return $date;
- }
-
- return $date->next($day);
- }
-
- $year = $this->year;
- $day = $this->dayOfYear;
- $date = $this->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
-
- if ($date->year === $year && $day < $date->dayOfYear) {
- return $year - 1;
- }
-
- $date = $this->copy()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
-
- if ($date->year === $year && $day >= $date->dayOfYear) {
- return $year + 1;
- }
-
- return $year;
- }
-
- /**
- * Get the number of weeks of the current week-year using given first day of week and first
- * day of year included in the first week. Or use ISO format if no settings
- * given.
- *
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int
- */
- public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null)
- {
- return $this->weeksInYear(
- $dayOfWeek ?? 1,
- $dayOfYear ?? 4
- );
- }
-
- /**
- * Get the number of weeks of the current week-year using given first day of week and first
- * day of year included in the first week. Or use US format if no settings
- * given (Sunday / Jan 6).
- *
- * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
- * @param int|null $dayOfYear first day of year included in the week #1
- *
- * @return int
- */
- public function weeksInYear($dayOfWeek = null, $dayOfYear = null)
- {
- $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
- $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
- $year = $this->year;
- $start = $this->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
- $startDay = $start->dayOfYear;
- if ($start->year !== $year) {
- $startDay -= $start->daysInYear;
- }
- $end = $this->copy()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
- $endDay = $end->dayOfYear;
- if ($end->year !== $year) {
- $endDay += $this->daysInYear;
- }
-
- return (int) round(($endDay - $startDay) / 7);
- }
-
- /**
- * Get/set the week number using given first day of week and first
- * day of year included in the first week. Or use US format if no settings
- * given (Sunday / Jan 6).
- *
- * @param int|null $week
- * @param int|null $dayOfWeek
- * @param int|null $dayOfYear
- *
- * @return int|static
- */
- public function week($week = null, $dayOfWeek = null, $dayOfYear = null)
- {
- $date = $this;
- $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
- $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
-
- if ($week !== null) {
- return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear));
- }
-
- $start = $date->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
- $end = $date->copy()->startOfWeek($dayOfWeek);
- if ($start > $end) {
- $start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
- }
- $week = (int) ($start->diffInDays($end) / 7 + 1);
-
- return $week > $end->weeksInYear($dayOfWeek, $dayOfYear) ? 1 : $week;
- }
-
- /**
- * Get/set the week number using given first day of week and first
- * day of year included in the first week. Or use ISO format if no settings
- * given.
- *
- * @param int|null $week
- * @param int|null $dayOfWeek
- * @param int|null $dayOfYear
- *
- * @return int|static
- */
- public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null)
- {
- return $this->week(
- $week,
- $dayOfWeek ?? 1,
- $dayOfYear ?? 4
- );
- }
-}
+++ /dev/null
-<?php
-
-/**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace Carbon;
-
-use Closure;
-use ReflectionException;
-use ReflectionFunction;
-use Symfony\Component\Translation;
-
-class Translator extends Translation\Translator
-{
- /**
- * Translator singletons for each language.
- *
- * @var array
- */
- protected static $singletons = [];
-
- /**
- * List of custom localized messages.
- *
- * @var array
- */
- protected $messages = [];
-
- /**
- * List of custom directories that contain translation files.
- *
- * @var array
- */
- protected $directories = [];
-
- /**
- * Set to true while constructing.
- *
- * @var bool
- */
- protected $initializing = false;
-
- /**
- * Return a singleton instance of Translator.
- *
- * @param string|null $locale optional initial locale ("en" - english by default)
- *
- * @return static
- */
- public static function get($locale = null)
- {
- $locale = $locale ?: 'en';
-
- if (!isset(static::$singletons[$locale])) {
- static::$singletons[$locale] = new static($locale ?: 'en');
- }
-
- return static::$singletons[$locale];
- }
-
- public function __construct($locale, Translation\Formatter\MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
- {
- $this->initializing = true;
- $this->directories = [__DIR__.'/Lang'];
- $this->addLoader('array', new Translation\Loader\ArrayLoader());
- parent::__construct($locale, $formatter, $cacheDir, $debug);
- $this->initializing = false;
- }
-
- /**
- * Returns the list of directories translation files are searched in.
- *
- * @return array
- */
- public function getDirectories(): array
- {
- return $this->directories;
- }
-
- /**
- * Set list of directories translation files are searched in.
- *
- * @param array $directories new directories list
- *
- * @return $this
- */
- public function setDirectories(array $directories)
- {
- $this->directories = $directories;
-
- return $this;
- }
-
- /**
- * Add a directory to the list translation files are searched in.
- *
- * @param string $directory new directory
- *
- * @return $this
- */
- public function addDirectory(string $directory)
- {
- $this->directories[] = $directory;
-
- return $this;
- }
-
- /**
- * Remove a directory from the list translation files are searched in.
- *
- * @param string $directory directory path
- *
- * @return $this
- */
- public function removeDirectory(string $directory)
- {
- $search = rtrim(strtr($directory, '\\', '/'), '/');
-
- return $this->setDirectories(array_filter($this->getDirectories(), function ($item) use ($search) {
- return rtrim(strtr($item, '\\', '/'), '/') !== $search;
- }));
- }
-
- /**
- * Returns the translation.
- *
- * @param string $id
- * @param array $parameters
- * @param string $domain
- * @param string $locale
- *
- * @return string
- */
- public function trans($id, array $parameters = [], $domain = null, $locale = null)
- {
- if (null === $domain) {
- $domain = 'messages';
- }
-
- $format = $this->getCatalogue($locale)->get((string) $id, $domain);
-
- if ($format instanceof Closure) {
- // @codeCoverageIgnoreStart
- try {
- $count = (new ReflectionFunction($format))->getNumberOfRequiredParameters();
- } catch (ReflectionException $exception) {
- $count = 0;
- }
- // @codeCoverageIgnoreEnd
-
- return $format(
- ...array_values($parameters),
- ...array_fill(0, max(0, $count - count($parameters)), null)
- );
- }
-
- return parent::trans($id, $parameters, $domain, $locale);
- }
-
- /**
- * Reset messages of a locale (all locale if no locale passed).
- * Remove custom messages and reload initial messages from matching
- * file in Lang directory.
- *
- * @param string|null $locale
- *
- * @return bool
- */
- public function resetMessages($locale = null)
- {
- if ($locale === null) {
- $this->messages = [];
-
- return true;
- }
-
- foreach ($this->getDirectories() as $directory) {
- $directory = rtrim($directory, '\\/');
- if (file_exists($filename = "$directory/$locale.php")) {
- $this->messages[$locale] = require $filename;
- $this->addResource('array', $this->messages[$locale], $locale);
-
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Returns the list of files matching a given locale prefix (or all if empty).
- *
- * @param string $prefix prefix required to filter result
- *
- * @return array
- */
- public function getLocalesFiles($prefix = '')
- {
- $files = [];
- foreach ($this->getDirectories() as $directory) {
- $directory = rtrim($directory, '\\/');
- foreach (glob("$directory/$prefix*.php") as $file) {
- $files[] = $file;
- }
- }
-
- return array_unique($files);
- }
-
- /**
- * Returns the list of internally available locales and already loaded custom locales.
- * (It will ignore custom translator dynamic loading.)
- *
- * @param string $prefix prefix required to filter result
- *
- * @return array
- */
- public function getAvailableLocales($prefix = '')
- {
- $locales = [];
- foreach ($this->getLocalesFiles($prefix) as $file) {
- $locales[] = substr($file, strrpos($file, '/') + 1, -4);
- }
-
- return array_unique(array_merge($locales, array_keys($this->messages)));
- }
-
- /**
- * Init messages language from matching file in Lang directory.
- *
- * @param string $locale
- *
- * @return bool
- */
- protected function loadMessagesFromFile($locale)
- {
- if (isset($this->messages[$locale])) {
- return true;
- }
-
- return $this->resetMessages($locale);
- }
-
- /**
- * Set messages of a locale and take file first if present.
- *
- * @param string $locale
- * @param array $messages
- *
- * @return $this
- */
- public function setMessages($locale, $messages)
- {
- $this->loadMessagesFromFile($locale);
- $this->addResource('array', $messages, $locale);
- $this->messages[$locale] = array_merge(
- isset($this->messages[$locale]) ? $this->messages[$locale] : [],
- $messages
- );
-
- return $this;
- }
-
- /**
- * Set messages of the current locale and take file first if present.
- *
- * @param array $messages
- *
- * @return $this
- */
- public function setTranslations($messages)
- {
- return $this->setMessages($this->getLocale(), $messages);
- }
-
- /**
- * Get messages of a locale, if none given, return all the
- * languages.
- *
- * @param string|null $locale
- *
- * @return array
- */
- public function getMessages($locale = null)
- {
- return $locale === null ? $this->messages : $this->messages[$locale];
- }
-
- /**
- * Set the current translator locale and indicate if the source locale file exists
- *
- * @param string $locale locale ex. en
- *
- * @return bool
- */
- public function setLocale($locale)
- {
- $locale = preg_replace_callback('/[-_]([a-z]{2,})/', function ($matches) {
- // _2-letters or YUE is a region, _3+-letters is a variant
- $upper = strtoupper($matches[1]);
-
- if ($upper === 'YUE' || $upper === 'ISO' || strlen($upper) < 3) {
- return "_$upper";
- }
-
- return '_'.ucfirst($matches[1]);
- }, strtolower($locale));
-
- if ($this->getLocale() === $locale) {
- return true;
- }
-
- if ($locale === 'auto') {
- $completeLocale = setlocale(LC_TIME, 0);
- $locale = preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale);
- $locales = $this->getAvailableLocales($locale);
-
- $completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale);
- $getScore = function ($language) use ($completeLocaleChunks) {
- $chunks = preg_split('/[_.-]+/', $language);
- $score = 0;
- foreach ($completeLocaleChunks as $index => $chunk) {
- if (!isset($chunks[$index])) {
- $score++;
-
- continue;
- }
- if (strtolower($chunks[$index]) === strtolower($chunk)) {
- $score += 10;
- }
- }
-
- return $score;
- };
- usort($locales, function ($a, $b) use ($getScore) {
- $a = $getScore($a);
- $b = $getScore($b);
-
- if ($a === $b) {
- return 0;
- }
-
- return $a < $b ? 1 : -1;
- });
- $locale = $locales[0];
- }
-
- // If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
- if (strpos($locale, '_') !== false &&
- $this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
- ) {
- parent::setLocale($macroLocale);
- }
-
- if ($this->loadMessagesFromFile($locale) || $this->initializing) {
- parent::setLocale($locale);
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Show locale on var_dump().
- *
- * @return array
- */
- public function __debugInfo()
- {
- return [
- 'locale' => $this->getLocale(),
- ];
- }
-}
--- /dev/null
+.idea/
+vendor/
\ No newline at end of file
--- /dev/null
+language: php
+sudo: false
+
+php:
+ - "7.2"
+ - "7.1"
+ - "7.0"
+ - "5.6"
+ - "hhvm"
+
+matrix:
+ fast_finish: true
+
+install:
+ - composer self-update
+ - composer update
+
+script:
+ - vendor/bin/phpunit
+ - vendor/bin/psalm
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2016 - 2018 Paragon Initiative Enterprises
+
+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.
+
+------------------------------------------------------------------------------
+This library was based on the work of Steve "Sc00bz" Thomas.
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Steve Thomas
+
+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.
+
--- /dev/null
+# Constant-Time Encoding
+
+[](https://travis-ci.org/paragonie/constant_time_encoding)
+
+Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding),
+this library aims to offer character encoding functions that do not leak
+information about what you are encoding/decoding via processor cache
+misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html).
+
+Our fork offers the following enchancements:
+
+* `mbstring.func_overload` resistance
+* Unit tests
+* Composer- and Packagist-ready
+* Base16 encoding
+* Base32 encoding
+* Uses `pack()` and `unpack()` instead of `chr()` and `ord()`
+
+## PHP Version Requirements
+
+This library should work on any [supported version of PHP](https://secure.php.net/supported-versions.php).
+It *may* work on earlier versions, but we **do not** guarantee it. If it
+doesn't, we **will not** fix it to work on earlier versions of PHP.
+
+## How to Install
+
+```sh
+composer require paragonie/constant_time_encoding
+```
+
+## How to Use
+
+```php
+use \ParagonIE\ConstantTime\Encoding;
+
+// possibly (if applicable):
+// require 'vendor/autoload.php';
+
+$data = random_bytes(32);
+echo Encoding::base64Encode($data), "\n";
+echo Encoding::base32EncodeUpper($data), "\n";
+echo Encoding::base32Encode($data), "\n";
+echo Encoding::hexEncode($data), "\n";
+echo Encoding::hexEncodeUpper($data), "\n";
+```
+
+Example output:
+
+```
+1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
+2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ====
+2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
+d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1
+D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1
+```
+
+If you only need a particular variant, you can just reference the
+required class like so:
+
+```php
+use \ParagonIE\ConstantTime\Base64;
+use \ParagonIE\ConstantTime\Base32;
+
+$data = random_bytes(32);
+echo Base64::encode($data), "\n";
+echo Base32::encode($data), "\n";
+```
+
+Example output:
+
+```
+1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
+2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
+```
\ No newline at end of file
--- /dev/null
+{
+ "name": "paragonie/constant_time_encoding",
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base64", "encoding", "rfc4648", "base32", "base16", "hex", "bin2hex", "hex2bin", "base64_encode", "base64_decode", "base32_encode", "base32_decode"
+ ],
+ "license": "MIT",
+ "type": "library",
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
+ "email": "info@paragonie.com",
+ "source": "https://github.com/paragonie/constant_time_encoding"
+ },
+ "require": {
+ "php": "^5.3|^7"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*",
+ "paragonie/random_compat": "^1.4|^2",
+ "vimeo/psalm": "^0.3|^1"
+ },
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="true"
+ backupStaticAttributes="false"
+ bootstrap="tests/autoload.php"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnError="false"
+ stopOnFailure="false"
+ syntaxCheck="true"
+>
+<testsuites>
+ <testsuite name="Constant Time Encoding Test Suite">
+ <directory suffix="Test.php">./tests</directory>
+ </testsuite>
+</testsuites>
+<filter>
+ <whitelist processUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./src</directory>
+ </whitelist>
+</filter>
+</phpunit>
--- /dev/null
+<?xml version="1.0"?>
+<psalm
+ name="Example Psalm config with recommended defaults"
+ stopOnFirstError="false"
+ useDocblockTypes="true"
+ totallyTyped="false"
+>
+ <projectFiles>
+ <directory name="src" />
+ </projectFiles>
+</psalm>
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Base32
+ * [A-Z][2-7]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base32 implements EncoderInterface
+{
+ /**
+ * Decode a Base32-encoded string into raw binary
+ *
+ * @param string $src
+ * @param bool $strictPadding
+ * @return string
+ */
+ public static function decode($src, $strictPadding = \false)
+ {
+ return static::doDecode($src, \false, $strictPadding);
+ }
+
+ /**
+ * Decode an uppercase Base32-encoded string into raw binary
+ *
+ * @param string $src
+ * @param bool $strictPadding
+ * @return string
+ */
+ public static function decodeUpper($src, $strictPadding = \false)
+ {
+ return static::doDecode($src, \true, $strictPadding);
+ }
+
+ /**
+ * Encode into Base32 (RFC 4648)
+ *
+ * @param string $src
+ * @return string
+ */
+ public static function encode($src)
+ {
+ return static::doEncode($src, \false);
+ }
+
+ /**
+ * Encode into Base32 (RFC 4648)
+ *
+ * @param string $src
+ * @return string
+ * @throws \TypeError
+ */
+ public static function encodeUnpadded($src)
+ {
+ return static::doEncode($src, false, false);
+ }
+
+ /**
+ * Encode into uppercase Base32 (RFC 4648)
+ *
+ * @param string $src
+ * @return string
+ */
+ public static function encodeUpper($src)
+ {
+ return static::doEncode($src, \true);
+ }
+
+ /**
+ * Encode into uppercase Base32 (RFC 4648)
+ *
+ * @param string $src
+ * @return string
+ * @throws \TypeError
+ */
+ public static function encodeUpperUnpadded($src)
+ {
+ return static::doEncode($src, true, false);
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+ * into 8-bit integers.
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode5Bits($src)
+ {
+ $ret = -1;
+
+ // if ($src > 96 && $src < 123) $ret += $src - 97 + 1; // -64
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 96);
+
+ // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
+ $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+ * into 8-bit integers.
+ *
+ * Uppercase variant.
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode5BitsUpper($src)
+ {
+ $ret = -1;
+
+ // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+ // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
+ $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5Bits($src)
+ {
+ $diff = 0x61;
+
+ // if ($src > 25) $ret -= 72;
+ $diff -= ((25 - $src) >> 8) & 73;
+
+ return \pack('C', $src + $diff);
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * Uppercase variant.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5BitsUpper($src)
+ {
+ $diff = 0x41;
+
+ // if ($src > 25) $ret -= 40;
+ $diff -= ((25 - $src) >> 8) & 41;
+
+ return \pack('C', $src + $diff);
+ }
+
+
+ /**
+ * Base32 decoding
+ *
+ * @param string $src
+ * @param bool $upper
+ * @param bool $strictPadding
+ * @return string
+ */
+ protected static function doDecode($src, $upper = \false, $strictPadding = \true)
+ {
+ // We do this to reduce code duplication:
+ $method = $upper
+ ? 'decode5BitsUpper'
+ : 'decode5Bits';
+
+ // Remove padding
+ $srcLen = Binary::safeStrlen($src);
+ if ($srcLen === 0) {
+ return '';
+ }
+ if ($strictPadding) {
+ if (($srcLen & 7) === 0) {
+ for ($j = 0; $j < 7; ++$j) {
+ if ($src[$srcLen - 1] === '=') {
+ $srcLen--;
+ } else {
+ break;
+ }
+ }
+ }
+ if (($srcLen & 7) === 1) {
+ throw new \RangeException(
+ 'Incorrect padding'
+ );
+ }
+ } else {
+ $src = \rtrim($src, '=');
+ $srcLen = Binary::safeStrlen($src);
+ }
+
+ $err = 0;
+ $dest = '';
+ // Main loop (no padding):
+ for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8));
+ $c0 = static::$method($chunk[1]);
+ $c1 = static::$method($chunk[2]);
+ $c2 = static::$method($chunk[3]);
+ $c3 = static::$method($chunk[4]);
+ $c4 = static::$method($chunk[5]);
+ $c5 = static::$method($chunk[6]);
+ $c6 = static::$method($chunk[7]);
+ $c7 = static::$method($chunk[8]);
+
+ $dest .= \pack(
+ 'CCCCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff,
+ (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff,
+ (($c6 << 5) | ($c7 ) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ $c0 = static::$method($chunk[1]);
+
+ if ($i + 6 < $srcLen) {
+ $c1 = static::$method($chunk[2]);
+ $c2 = static::$method($chunk[3]);
+ $c3 = static::$method($chunk[4]);
+ $c4 = static::$method($chunk[5]);
+ $c5 = static::$method($chunk[6]);
+ $c6 = static::$method($chunk[7]);
+
+ $dest .= \pack(
+ 'CCCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff,
+ (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
+ } elseif ($i + 5 < $srcLen) {
+ $c1 = static::$method($chunk[2]);
+ $c2 = static::$method($chunk[3]);
+ $c3 = static::$method($chunk[4]);
+ $c4 = static::$method($chunk[5]);
+ $c5 = static::$method($chunk[6]);
+
+ $dest .= \pack(
+ 'CCCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff,
+ (($c4 << 7) | ($c5 << 2) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
+ } elseif ($i + 4 < $srcLen) {
+ $c1 = static::$method($chunk[2]);
+ $c2 = static::$method($chunk[3]);
+ $c3 = static::$method($chunk[4]);
+ $c4 = static::$method($chunk[5]);
+
+ $dest .= \pack(
+ 'CCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
+ } elseif ($i + 3 < $srcLen) {
+ $c1 = static::$method($chunk[2]);
+ $c2 = static::$method($chunk[3]);
+ $c3 = static::$method($chunk[4]);
+
+ $dest .= \pack(
+ 'CC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
+ } elseif ($i + 2 < $srcLen) {
+ $c1 = static::$method($chunk[2]);
+ $c2 = static::$method($chunk[3]);
+
+ $dest .= \pack(
+ 'CC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2) >> 8;
+ } elseif ($i + 1 < $srcLen) {
+ $c1 = static::$method($chunk[2]);
+
+ $dest .= \pack(
+ 'C',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff
+ );
+ $err |= ($c0 | $c1) >> 8;
+ } else {
+ $dest .= \pack(
+ 'C',
+ (($c0 << 3) ) & 0xff
+ );
+ $err |= ($c0) >> 8;
+ }
+ }
+ if ($err !== 0) {
+ throw new \RangeException(
+ 'Base32::doDecode() only expects characters in the correct base32 alphabet'
+ );
+ }
+ return $dest;
+ }
+
+ /**
+ * Base32 Decoding
+ *
+ * @param string $src
+ * @param bool $upper
+ * @param bool $pad
+ * @return string
+ */
+ protected static function doEncode($src, $upper = \false, $pad = \true)
+ {
+ // We do this to reduce code duplication:
+ $method = $upper
+ ? 'encode5BitsUpper'
+ : 'encode5Bits';
+
+ $dest = '';
+ $srcLen = Binary::safeStrlen($src);
+
+ // Main loop (no padding):
+ for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5));
+ $b0 = $chunk[1];
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+ $b3 = $chunk[4];
+ $b4 = $chunk[5];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+ static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
+ static::$method((($b3 >> 2) ) & 31) .
+ static::$method((($b3 << 3) | ($b4 >> 5)) & 31) .
+ static::$method( $b4 & 31);
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ $b0 = $chunk[1];
+ if ($i + 3 < $srcLen) {
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+ $b3 = $chunk[4];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+ static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
+ static::$method((($b3 >> 2) ) & 31) .
+ static::$method((($b3 << 3) ) & 31);
+ if ($pad) {
+ $dest .= '=';
+ }
+ } elseif ($i + 2 < $srcLen) {
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+ static::$method((($b2 << 1) ) & 31);
+ if ($pad) {
+ $dest .= '===';
+ }
+ } elseif ($i + 1 < $srcLen) {
+ $b1 = $chunk[2];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) ) & 31);
+ if ($pad) {
+ $dest .= '====';
+ }
+ } else {
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method( ($b0 << 2) & 31);
+ if ($pad) {
+ $dest .= '======';
+ }
+ }
+ }
+ return $dest;
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Base32Hex
+ * [0-9][A-V]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base32Hex extends Base32
+{
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+ * into 8-bit integers.
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode5Bits($src)
+ {
+ $ret = -1;
+
+ // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
+
+ // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
+ $ret += (((0x60 - $src) & ($src - 0x77)) >> 8) & ($src - 86);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+ * into 8-bit integers.
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode5BitsUpper($src)
+ {
+ $ret = -1;
+
+ // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
+
+ // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
+ $ret += (((0x40 - $src) & ($src - 0x57)) >> 8) & ($src - 54);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5Bits($src)
+ {
+ $src += 0x30;
+
+ // if ($src > 0x39) $src += 0x61 - 0x3a; // 39
+ $src += ((0x39 - $src) >> 8) & 39;
+
+ return \pack('C', $src);
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * Uppercase variant.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5BitsUpper($src)
+ {
+ $src += 0x30;
+
+ // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
+ $src += ((0x39 - $src) >> 8) & 7;
+
+ return \pack('C', $src);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Base64
+ * [A-Z][a-z][0-9]+/
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64 implements EncoderInterface
+{
+ /**
+ * Encode into Base64
+ *
+ * Base64 character set "[A-Z][a-z][0-9]+/"
+ *
+ * @param string $src
+ * @return string
+ */
+ public static function encode($src)
+ {
+ return static::doEncode($src, \true);
+ }
+
+ /**
+ * Encode into Base64, no = padding
+ *
+ * Base64 character set "[A-Z][a-z][0-9]+/"
+ *
+ * @param string $src
+ * @return string
+ */
+ public static function encodeUnpadded($src)
+ {
+ return static::doEncode($src, \false);
+ }
+
+ /**
+ * @param string $src
+ * @param bool $pad Include = padding?
+ * @return string
+ */
+ protected static function doEncode($src, $pad = \true)
+ {
+ $dest = '';
+ $srcLen = Binary::safeStrlen($src);
+ // Main loop (no padding):
+ for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
+ $b0 = $chunk[1];
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+
+ $dest .=
+ static::encode6Bits( $b0 >> 2 ) .
+ static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
+ static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
+ static::encode6Bits( $b2 & 63);
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ $b0 = $chunk[1];
+ if ($i + 1 < $srcLen) {
+ $b1 = $chunk[2];
+ $dest .=
+ static::encode6Bits( $b0 >> 2 ) .
+ static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
+ static::encode6Bits( ($b1 << 2) & 63);
+ if ($pad) {
+ $dest .= '=';
+ }
+ } else {
+ $dest .=
+ static::encode6Bits( $b0 >> 2) .
+ static::encode6Bits(($b0 << 4) & 63);
+ if ($pad) {
+ $dest .= '==';
+ }
+ }
+ }
+ return $dest;
+ }
+
+ /**
+ * decode from base64 into binary
+ *
+ * Base64 character set "./[A-Z][a-z][0-9]"
+ *
+ * @param string $src
+ * @param bool $strictPadding
+ * @return string
+ * @throws \RangeException
+ */
+ public static function decode($src, $strictPadding = \false)
+ {
+ // Remove padding
+ $srcLen = Binary::safeStrlen($src);
+ if ($srcLen === 0) {
+ return '';
+ }
+ if ($strictPadding) {
+ if (($srcLen & 3) === 0) {
+ if ($src[$srcLen - 1] === '=') {
+ $srcLen--;
+ if ($src[$srcLen - 1] === '=') {
+ $srcLen--;
+ }
+ }
+ }
+ if (($srcLen & 3) === 1) {
+ throw new \RangeException(
+ 'Incorrect padding'
+ );
+ }
+ } else {
+ $src = \rtrim($src, '=');
+ $srcLen = Binary::safeStrlen($src);
+ }
+
+ $err = 0;
+ $dest = '';
+ // Main loop (no padding):
+ for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 4));
+ $c0 = static::decode6Bits($chunk[1]);
+ $c1 = static::decode6Bits($chunk[2]);
+ $c2 = static::decode6Bits($chunk[3]);
+ $c3 = static::decode6Bits($chunk[4]);
+
+ $dest .= \pack(
+ 'CCC',
+ ((($c0 << 2) | ($c1 >> 4)) & 0xff),
+ ((($c1 << 4) | ($c2 >> 2)) & 0xff),
+ ((($c2 << 6) | $c3 ) & 0xff)
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ $c0 = static::decode6Bits($chunk[1]);
+ if ($i + 2 < $srcLen) {
+ $c1 = static::decode6Bits($chunk[2]);
+ $c2 = static::decode6Bits($chunk[3]);
+ $dest .= \pack(
+ 'CC',
+ ((($c0 << 2) | ($c1 >> 4)) & 0xff),
+ ((($c1 << 4) | ($c2 >> 2)) & 0xff)
+ );
+ $err |= ($c0 | $c1 | $c2) >> 8;
+ } elseif($i + 1 < $srcLen) {
+ $c1 = static::decode6Bits($chunk[2]);
+ $dest .= \pack(
+ 'C',
+ ((($c0 << 2) | ($c1 >> 4)) & 0xff)
+ );
+ $err |= ($c0 | $c1) >> 8;
+ } elseif ($i < $srcLen && $strictPadding) {
+ $err |= 1;
+ }
+ }
+ if ($err !== 0) {
+ throw new \RangeException(
+ 'Base64::decode() only expects characters in the correct base64 alphabet'
+ );
+ }
+ return $dest;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+ * into 8-bit integers.
+ *
+ * Base64 character set:
+ * [A-Z] [a-z] [0-9] + /
+ * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode6Bits($src)
+ {
+ $ret = -1;
+
+ // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+ // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
+
+ // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
+
+ // if ($src == 0x2b) $ret += 62 + 1;
+ $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
+
+ // if ($src == 0x2f) ret += 63 + 1;
+ $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits($src)
+ {
+ $diff = 0x41;
+
+ // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
+ $diff += ((25 - $src) >> 8) & 6;
+
+ // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
+ $diff -= ((51 - $src) >> 8) & 75;
+
+ // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
+ $diff -= ((61 - $src) >> 8) & 15;
+
+ // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
+ $diff += ((62 - $src) >> 8) & 3;
+
+ return \pack('C', $src + $diff);
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Base64DotSlash
+ * ./[A-Z][a-z][0-9]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64DotSlash extends Base64
+{
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+ * into 8-bit integers.
+ *
+ * Base64 character set:
+ * ./ [A-Z] [a-z] [0-9]
+ * 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode6Bits($src)
+ {
+ $ret = -1;
+
+ // if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
+ $ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45);
+
+ // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62);
+
+ // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68);
+
+ // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits($src)
+ {
+ $src += 0x2e;
+
+ // if ($src > 0x2f) $src += 0x41 - 0x30; // 17
+ $src += ((0x2f - $src) >> 8) & 17;
+
+ // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
+ $src += ((0x5a - $src) >> 8) & 6;
+
+ // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
+ $src -= ((0x7a - $src) >> 8) & 75;
+
+ return \pack('C', $src);
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Base64DotSlashOrdered
+ * ./[0-9][A-Z][a-z]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64DotSlashOrdered extends Base64
+{
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+ * into 8-bit integers.
+ *
+ * Base64 character set:
+ * [.-9] [A-Z] [a-z]
+ * 0x2e-0x39, 0x41-0x5a, 0x61-0x7a
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode6Bits($src)
+ {
+ $ret = -1;
+
+ // if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
+ $ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45);
+
+ // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52);
+
+ // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits($src)
+ {
+ $src += 0x2e;
+
+ // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
+ $src += ((0x39 - $src) >> 8) & 7;
+
+ // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
+ $src += ((0x5a - $src) >> 8) & 6;
+
+ return \pack('C', $src);
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Base64DotSlash
+ * ./[A-Z][a-z][0-9]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64UrlSafe extends Base64
+{
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+ * into 8-bit integers.
+ *
+ * Base64 character set:
+ * [A-Z] [a-z] [0-9] - _
+ * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2d, 0x5f
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode6Bits($src)
+ {
+ $ret = -1;
+
+ // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+ // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
+
+ // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
+
+ // if ($src == 0x2c) $ret += 62 + 1;
+ $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;
+
+ // if ($src == 0x5f) ret += 63 + 1;
+ $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits($src)
+ {
+ $diff = 0x41;
+
+ // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
+ $diff += ((25 - $src) >> 8) & 6;
+
+ // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
+ $diff -= ((51 - $src) >> 8) & 75;
+
+ // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
+ $diff -= ((61 - $src) >> 8) & 13;
+
+ // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
+ $diff += ((62 - $src) >> 8) & 49;
+
+ return \pack('C', $src + $diff);
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Binary
+ *
+ * Binary string operators that don't choke on
+ * mbstring.func_overload
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Binary
+{
+ /**
+ * Safe string length
+ *
+ * @ref mbstring.func_overload
+ *
+ * @param string $str
+ * @return int
+ */
+ public static function safeStrlen($str)
+ {
+ if (\function_exists('mb_strlen')) {
+ return (int) \mb_strlen($str, '8bit');
+ } else {
+ return (int) \strlen($str);
+ }
+ }
+
+ /**
+ * Safe substring
+ *
+ * @ref mbstring.func_overload
+ *
+ * @staticvar boolean $exists
+ * @param string $str
+ * @param int $start
+ * @param int $length
+ * @return string
+ * @throws \TypeError
+ */
+ public static function safeSubstr(
+ $str,
+ $start = 0,
+ $length = \null
+ ) {
+ if (\function_exists('mb_substr')) {
+ // mb_substr($str, 0, null, '8bit') returns an empty string on PHP
+ // 5.3, so we have to find the length ourselves.
+ if (\is_null($length)) {
+ if ($start >= 0) {
+ $length = self::safeStrlen($str) - $start;
+ } else {
+ $length = -$start;
+ }
+ }
+ // $length calculation above might result in a 0-length string
+ if ($length === 0) {
+ return '';
+ }
+ return \mb_substr($str, $start, $length, '8bit');
+ }
+ if ($length === 0) {
+ return '';
+ }
+ // Unlike mb_substr(), substr() doesn't accept null for length
+ if (!is_null($length)) {
+ return \substr($str, $start, $length);
+ } else {
+ return \substr($str, $start);
+ }
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Interface EncoderInterface
+ * @package ParagonIE\ConstantTime
+ */
+interface EncoderInterface
+{
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks
+ *
+ * @param string $bin_string (raw binary)
+ * @return string
+ */
+ public static function encode($bin_string);
+
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks
+ *
+ * @param string $encoded_string
+ * @return string (raw binary)
+ */
+ public static function decode($encoded_string);
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Encoding
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Encoding
+{
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32Encode($str)
+ {
+ return Base32::encode($str);
+ }
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32EncodeUpper($str)
+ {
+ return Base32::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32 decoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32Decode($str)
+ {
+ return Base32::decode($str);
+ }
+
+ /**
+ * RFC 4648 Base32 decoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32DecodeUpper($str)
+ {
+ return Base32::decodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32HexEncode($str)
+ {
+ return Base32Hex::encode($str);
+ }
+
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32HexEncodeUpper($str)
+ {
+ return Base32Hex::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32 decoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32HexDecode($str)
+ {
+ return Base32Hex::decode($str);
+ }
+
+ /**
+ * RFC 4648 Base32 decoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base32HexDecodeUpper($str)
+ {
+ return Base32Hex::decodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base64 encoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base64Encode($str)
+ {
+ return Base64::encode($str);
+ }
+
+ /**
+ * RFC 4648 Base32 decoding
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base64Decode($str)
+ {
+ return Base64::decode($str);
+ }
+
+ /**
+ * Encode into Base64
+ *
+ * Base64 character set "./[A-Z][a-z][0-9]"
+ * @param string $src
+ * @return string
+ */
+ public static function base64EncodeDotSlash($src)
+ {
+ return Base64DotSlash::encode($src);
+ }
+
+ /**
+ * Decode from base64 to raw binary
+ *
+ * Base64 character set "./[A-Z][a-z][0-9]"
+ *
+ * @param string $src
+ * @return string
+ * @throws \RangeException
+ */
+ public static function base64DecodeDotSlash($src)
+ {
+ return Base64DotSlash::decode($src);
+ }
+
+ /**
+ * Encode into Base64
+ *
+ * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
+ * @param string $src
+ * @return string
+ */
+ public static function base64EncodeDotSlashOrdered($src)
+ {
+ return Base64DotSlashOrdered::encode($src);
+ }
+
+ /**
+ * Decode from base64 to raw binary
+ *
+ * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
+ *
+ * @param string $src
+ * @return string
+ * @throws \RangeException
+ */
+ public static function base64DecodeDotSlashOrdered($src)
+ {
+ return Base64DotSlashOrdered::decode($src);
+ }
+
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks
+ *
+ * @param string $bin_string (raw binary)
+ * @return string
+ */
+ public static function hexEncode($bin_string)
+ {
+ return Hex::encode($bin_string);
+ }
+
+ /**
+ * Convert a hexadecimal string into a binary string without cache-timing
+ * leaks
+ *
+ * @param string $hex_string
+ * @return string (raw binary)
+ * @throws \RangeException
+ */
+ public static function hexDecode($hex_string)
+ {
+ return Hex::decode($hex_string);
+ }
+
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks
+ *
+ * @param string $bin_string (raw binary)
+ * @return string
+ */
+ public static function hexEncodeUpper($bin_string)
+ {
+ return Hex::encodeUpper($bin_string);
+ }
+
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks
+ *
+ * @param string $bin_string (raw binary)
+ * @return string
+ */
+ public static function hexDecodeUpper($bin_string)
+ {
+ return Hex::decode($bin_string);
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class Hex
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Hex implements EncoderInterface
+{
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks
+ *
+ * @param string $bin_string (raw binary)
+ * @return string
+ */
+ public static function encode($bin_string)
+ {
+ $hex = '';
+ $len = Binary::safeStrlen($bin_string);
+ for ($i = 0; $i < $len; ++$i) {
+ $chunk = \unpack('C', Binary::safeSubstr($bin_string, $i, 2));
+ $c = $chunk[1] & 0xf;
+ $b = $chunk[1] >> 4;
+ $hex .= pack(
+ 'CC',
+ (87 + $b + ((($b - 10) >> 8) & ~38)),
+ (87 + $c + ((($c - 10) >> 8) & ~38))
+ );
+ }
+ return $hex;
+ }
+
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks, returning uppercase letters (as per RFC 4648)
+ *
+ * @param string $bin_string (raw binary)
+ * @return string
+ */
+ public static function encodeUpper($bin_string)
+ {
+ $hex = '';
+ $len = Binary::safeStrlen($bin_string);
+ for ($i = 0; $i < $len; ++$i) {
+ $chunk = \unpack('C', Binary::safeSubstr($bin_string, $i, 2));
+ $c = $chunk[1] & 0xf;
+ $b = $chunk[1] >> 4;
+ $hex .= pack(
+ 'CC',
+ (55 + $b + ((($b - 10) >> 8) & ~6)),
+ (55 + $c + ((($c - 10) >> 8) & ~6))
+ );
+ }
+ return $hex;
+ }
+
+ /**
+ * Convert a hexadecimal string into a binary string without cache-timing
+ * leaks
+ *
+ * @param string $hex_string
+ * @return string (raw binary)
+ * @throws \RangeException
+ */
+ public static function decode($hex_string)
+ {
+ $hex_pos = 0;
+ $bin = '';
+ $c_acc = 0;
+ $hex_len = Binary::safeStrlen($hex_string);
+ $state = 0;
+ if (($hex_len & 1) !== 0) {
+ throw new \RangeException(
+ 'Expected an even number of hexadecimal characters'
+ );
+ }
+
+ $chunk = \unpack('C*', $hex_string);
+ while ($hex_pos < $hex_len) {
+ ++$hex_pos;
+ $c = $chunk[$hex_pos];
+ $c_num = $c ^ 48;
+ $c_num0 = ($c_num - 10) >> 8;
+ $c_alpha = ($c & ~32) - 55;
+ $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
+ if (($c_num0 | $c_alpha0) === 0) {
+ throw new \RangeException(
+ 'hexEncode() only expects hexadecimal characters'
+ );
+ }
+ $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
+ if ($state === 0) {
+ $c_acc = $c_val * 16;
+ } else {
+ $bin .= \pack('C', $c_acc | $c_val);
+ }
+ $state ^= 1;
+ }
+ return $bin;
+ }
+}
--- /dev/null
+<?php
+namespace ParagonIE\ConstantTime;
+
+/**
+ * Copyright (c) 2016 - 2017 Paragon Initiative Enterprises.
+ * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ * 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.
+ */
+
+/**
+ * Class RFC4648
+ *
+ * This class conforms strictly to the RFC
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class RFC4648
+{
+ /**
+ * RFC 4648 Base64 encoding
+ *
+ * "foo" -> "Zm9v"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base64Encode($str)
+ {
+ return Base64::encode($str);
+ }
+
+ /**
+ * RFC 4648 Base64 decoding
+ *
+ * "Zm9v" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base64Decode($str)
+ {
+ return Base64::decode($str);
+ }
+
+ /**
+ * RFC 4648 Base64 (URL Safe) encoding
+ *
+ * "foo" -> "Zm9v"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base64UrlSafeEncode($str)
+ {
+ return Base64UrlSafe::encode($str);
+ }
+
+ /**
+ * RFC 4648 Base64 (URL Safe) decoding
+ *
+ * "Zm9v" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base64UrlSafeDecode($str)
+ {
+ return Base64UrlSafe::decode($str);
+ }
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * "foo" -> "MZXW6==="
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base32Encode($str)
+ {
+ return Base32::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * "MZXW6===" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base32Decode($str)
+ {
+ return Base32::decodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32-Hex encoding
+ *
+ * "foo" -> "CPNMU==="
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base32HexEncode($str)
+ {
+ return Base32::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32-Hex decoding
+ *
+ * "CPNMU===" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base32HexDecode($str)
+ {
+ return Base32::decodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base16 decoding
+ *
+ * "foo" -> "666F6F"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base16Encode($str)
+ {
+ return Hex::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base16 decoding
+ *
+ * "666F6F" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ */
+ public function base16Decode($str)
+ {
+ return Hex::decode($str);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base32Hex;
+
+class Base32HexTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Base32Hex::encode()
+ * @covers Base32Hex::decode()
+ * @covers Base32Hex::encodeUpper()
+ * @covers Base32Hex::decodeUpper()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Base32Hex::encode($random);
+ $this->assertSame(
+ $random,
+ Base32Hex::decode($enc)
+ );
+
+ $enc = Base32Hex::encodeUpper($random);
+ $this->assertSame(
+ $random,
+ Base32Hex::decodeUpper($enc)
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base32;
+
+class Base32Test extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Base32::encode()
+ * @covers Base32::decode()
+ * @covers Base32::encodeUpper()
+ * @covers Base32::decodeUpper()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Base32::encode($random);
+ $this->assertSame(
+ $random,
+ Base32::decode($enc)
+ );
+
+ $this->assertSame(
+ Base32::encodeUnpadded($random),
+ \rtrim(Base32::encode($random), '=')
+ );
+
+ $enc = Base32::encodeUpper($random);
+ $this->assertSame(
+ $random,
+ Base32::decodeUpper($enc)
+ );
+
+ $this->assertSame(
+ Base32::encodeUpperUnpadded($random),
+ \rtrim(Base32::encodeUpper($random), '=')
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
+
+class Base64DotSlashOrderedTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Base64DotSlashOrdered::encode()
+ * @covers Base64DotSlashOrdered::decode()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Base64DotSlashOrdered::encode($random);
+ $this->assertSame(
+ $random,
+ Base64DotSlashOrdered::decode($enc)
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base64DotSlash;
+
+class Base64DotSlashTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Base64DotSlash::encode()
+ * @covers Base64DotSlash::decode()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Base64DotSlash::encode($random);
+ $this->assertSame(
+ $random,
+ Base64DotSlash::decode($enc)
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base64;
+
+class Base64Test extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Base64::encode()
+ * @covers Base64::decode()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Base64::encode($random);
+ $this->assertSame(
+ $random,
+ Base64::decode($enc)
+ );
+ $this->assertSame(
+ \base64_encode($random),
+ $enc
+ );
+
+ $unpadded = \rtrim($enc, '=');
+ $this->assertSame(
+ $random,
+ Base64::decode($unpadded, false)
+ );
+ $extra_pad = $enc . '=======';
+
+ $this->assertSame(
+ $random,
+ Base64::decode($extra_pad, false)
+ );
+ }
+ }
+
+ $str = 'MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBM' .
+ 'MSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQ' .
+ 'DDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1Oi' .
+ 'A2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNVBAYTAlBMM' .
+ 'RwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQRVNFTDogNjEw' .
+ 'NjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBNBgNVBBAwRgwiQWw' .
+ 'uIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEtMzgyIEdkeW5pYQwGUG' .
+ '9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMwEQYDVQQEDApQcnpld29yc' .
+ '2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMm5vjGqHPthJCMqKpqssSISRo' .
+ 's0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBNZfjUl7r8dIi28bSKhNlsfycXZKY' .
+ 'RcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+uLLcJVTHCu0w9oXLGbRlGth5eNoj03C' .
+ 'xXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYDVR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCA' .
+ 'TwwggE4MIIBNAYJKoRoAYb3IwEBMIIBJTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJh' .
+ 'Y2phIHRhIGplc3Qgb8Wbd2lhZGN6ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZ' .
+ 'pa2F0IHpvc3RhxYIgd3lkYW55IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IH' .
+ 'pnb2RuaWUgeiB3eW1hZ2FuaWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmlje' .
+ 'm55bSBvcmF6IHRvd2FyenlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMG' .
+ 'CCsGAQUFBwIBFjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN' .
+ '6eS9wb2xpdHlrYS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2' .
+ 'tpQGdkeW5pYS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXip' .
+ 'N4oGS3ZYmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dh' .
+ 'IEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt' .
+ '3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/MD' .
+ '2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9DU' .
+ 'kxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJjcar/qWZ' .
+ 'y9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2ZKQmi+cIHJHL' .
+ 'ONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7zXZq/cLL0If0hX' .
+ 'oPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGLf3kHVzgM6j3VAM7oF' .
+ 'mMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9f/1y2XuLNhBNHMAyTqpY' .
+ 'PX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelUMj93S';
+
+ $str = preg_replace('#[\r\n]#', '', $str);
+ $this->assertSame(
+ Base64::decode($str),
+ \base64_decode($str)
+ );
+
+ $str = 'zbhle48rXrbJUdodb6FAQvkj0W/vDhBzt/mZiCTpaJ/zumnG1wCDuEQBoh9P';
+ $this->assertSame(
+ Base64::decode($str),
+ \base64_decode($str)
+ );
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base64UrlSafe;
+
+class Base64UrlSafeTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Base64UrlSafe::encode()
+ * @covers Base64UrlSafe::decode()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Base64UrlSafe::encode($random);
+ $this->assertSame(
+ $random,
+ Base64UrlSafe::decode($enc)
+ );
+ $this->assertSame(
+ \strtr(\base64_encode($random), '+/', '-_'),
+ $enc
+ );
+ $unpadded = \rtrim($enc, '=');
+ $this->assertSame(
+ $unpadded,
+ Base64UrlSafe::encodeUnpadded($random)
+ );
+ $this->assertSame(
+ $random,
+ Base64UrlSafe::decode($unpadded)
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base32;
+use \ParagonIE\ConstantTime\Base32Hex;
+use \ParagonIE\ConstantTime\Base64;
+use \ParagonIE\ConstantTime\Base64DotSlash;
+use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
+use \ParagonIE\ConstantTime\Base64UrlSafe;
+use \ParagonIE\ConstantTime\Encoding;
+use \ParagonIE\ConstantTime\Hex;
+
+class EncodingTest extends PHPUnit_Framework_TestCase
+{
+ public function testBase32Encode()
+ {
+ $this->assertSame(
+ Encoding::base32Encode("\x00"),
+ 'aa======'
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\x00\x00"),
+ 'aaaa===='
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\x00\x00\x00"),
+ 'aaaaa==='
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\x00\x00\x00\x00"),
+ 'aaaaaaa='
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\x00\x00\x00\x00\x00"),
+ 'aaaaaaaa'
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\x00\x00\x0F\xFF\xFF"),
+ 'aaaa7777'
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\xFF\xFF\xF0\x00\x00"),
+ '7777aaaa'
+ );
+
+ $this->assertSame(
+ Encoding::base32Encode("\xce\x73\x9c\xe7\x39"),
+ 'zzzzzzzz'
+ );
+ $this->assertSame(
+ Encoding::base32Encode("\xd6\xb5\xad\x6b\x5a"),
+ '22222222'
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\x00"),
+ 'AA======'
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\x00\x00"),
+ 'AAAA===='
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\x00\x00\x00"),
+ 'AAAAA==='
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\x00\x00\x00\x00"),
+ 'AAAAAAA='
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\x00\x00\x00\x00\x00"),
+ 'AAAAAAAA'
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\x00\x00\x0F\xFF\xFF"),
+ 'AAAA7777'
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\xFF\xFF\xF0\x00\x00"),
+ '7777AAAA'
+ );
+
+ $this->assertSame(
+ Base32::encodeUpper("\xce\x73\x9c\xe7\x39"),
+ 'ZZZZZZZZ'
+ );
+ $this->assertSame(
+ Base32::encodeUpper("\xd6\xb5\xad\x6b\x5a"),
+ '22222222'
+ );
+ }
+
+ public function testBase32Hex()
+ {
+ $this->assertSame(
+ Base32Hex::encode("\x00"),
+ '00======'
+ );
+ $this->assertSame(
+ Base32Hex::encode("\x00\x00"),
+ '0000===='
+ );
+ $this->assertSame(
+ Base32Hex::encode("\x00\x00\x00"),
+ '00000==='
+ );
+ $this->assertSame(
+ Base32Hex::encode("\x00\x00\x00\x00"),
+ '0000000='
+ );
+ $this->assertSame(
+ Base32Hex::encode("\x00\x00\x00\x00\x00"),
+ '00000000'
+ );
+ $this->assertSame(
+ Base32Hex::encode("\x00\x00\x0F\xFF\xFF"),
+ '0000vvvv'
+ );
+ $this->assertSame(
+ Base32Hex::encode("\xFF\xFF\xF0\x00\x00"),
+ 'vvvv0000'
+ );
+
+
+ }
+
+ /**
+ * Based on test vectors from RFC 4648
+ */
+ public function testBase32Decode()
+ {
+ $this->assertSame(
+ "\x00\x00\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaaaaa======')
+ );
+ $this->assertSame(
+ "\x00\x00\x00\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaaaaaaa====')
+ );
+ $this->assertSame(
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaaaaaaaa===')
+ );
+ $this->assertSame(
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaaaaaaaaaa=')
+ );
+ $this->assertSame(
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaaaaaaaaaaa')
+ );
+ $this->assertSame(
+ "\x00",
+ Encoding::base32Decode('aa======')
+ );
+ $this->assertSame(
+ "\x00\x00",
+ Encoding::base32Decode('aaaa====')
+ );
+ $this->assertSame(
+ "\x00\x00\x00",
+ Encoding::base32Decode('aaaaa===')
+ );
+ $this->assertSame(
+ "\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaa=')
+ );
+ $this->assertSame(
+ "\x00\x00\x00\x00\x00",
+ Encoding::base32Decode('aaaaaaaa')
+ );
+ $this->assertSame(
+ "\x00\x00\x0F\xFF\xFF",
+ Encoding::base32Decode('aaaa7777')
+ );
+ $this->assertSame(
+ "\xFF\xFF\xF0\x00\x00",
+ Encoding::base32Decode('7777aaaa')
+ );
+ $this->assertSame(
+ "\xce\x73\x9c\xe7\x39",
+ Encoding::base32Decode('zzzzzzzz')
+ );
+ $this->assertSame(
+ "\xd6\xb5\xad\x6b\x5a",
+ Encoding::base32Decode('22222222')
+ );
+ $this->assertSame(
+ 'foobar',
+ Encoding::base32Decode('mzxw6ytboi======')
+ );
+
+ $rand = random_bytes(9);
+ $enc = Encoding::base32Encode($rand);
+
+ $this->assertSame(
+ Encoding::base32Encode($rand),
+ Encoding::base32Encode(Encoding::base32Decode($enc))
+ );
+ $this->assertSame(
+ $rand,
+ Encoding::base32Decode($enc)
+ );
+ }
+
+ /**
+ * @covers Encoding::hexDecode()
+ * @covers Encoding::hexEncode()
+ * @covers Encoding::base32Decode()
+ * @covers Encoding::base32Encode()
+ * @covers Encoding::base64Decode()
+ * @covers Encoding::base64Encode()
+ * @covers Encoding::base64DotSlashDecode()
+ * @covers Encoding::base64DotSlashEncode()
+ * @covers Encoding::base64DotSlashOrderedDecode()
+ * @covers Encoding::base64DotSlashOrderedEncode()
+ */
+ public function testBasicEncoding()
+ {
+ // Re-run the test at least 3 times for each length
+ for ($j = 0; $j < 3; ++$j) {
+ for ($i = 1; $i < 84; ++$i) {
+ $rand = random_bytes($i);
+ $enc = Encoding::hexEncode($rand);
+ $this->assertSame(
+ \bin2hex($rand),
+ $enc,
+ "Hex Encoding - Length: " . $i
+ );
+ $this->assertSame(
+ $rand,
+ Encoding::hexDecode($enc),
+ "Hex Encoding - Length: " . $i
+ );
+
+ // Uppercase variant:
+ $enc = Hex::encodeUpper($rand);
+ $this->assertSame(
+ \strtoupper(\bin2hex($rand)),
+ $enc,
+ "Hex Encoding - Length: " . $i
+ );
+ $this->assertSame(
+ $rand,
+ Hex::decode($enc),
+ "HexUpper Encoding - Length: " . $i
+ );
+
+ $enc = Encoding::base32Encode($rand);
+ $this->assertSame(
+ $rand,
+ Encoding::base32Decode($enc),
+ "Base32 Encoding - Length: " . $i
+ );
+
+ $enc = Encoding::base32EncodeUpper($rand);
+ $this->assertSame(
+ $rand,
+ Encoding::base32DecodeUpper($enc),
+ "Base32Upper Encoding - Length: " . $i
+ );
+
+ $enc = Encoding::base32HexEncode($rand);
+ $this->assertSame(
+ bin2hex($rand),
+ bin2hex(Encoding::base32HexDecode($enc)),
+ "Base32Hex Encoding - Length: " . $i
+ );
+
+ $enc = Encoding::base32HexEncodeUpper($rand);
+ $this->assertSame(
+ bin2hex($rand),
+ bin2hex(Encoding::base32HexDecodeUpper($enc)),
+ "Base32HexUpper Encoding - Length: " . $i
+ );
+
+ $enc = Encoding::base64Encode($rand);
+ $this->assertSame(
+ $rand,
+ Encoding::base64Decode($enc),
+ "Base64 Encoding - Length: " . $i
+ );
+
+ $enc = Encoding::base64EncodeDotSlash($rand);
+ $this->assertSame(
+ $rand,
+ Encoding::base64DecodeDotSlash($enc),
+ "Base64 DotSlash Encoding - Length: " . $i
+ );
+ $enc = Encoding::base64EncodeDotSlashOrdered($rand);
+ $this->assertSame(
+ $rand,
+ Encoding::base64DecodeDotSlashOrdered($enc),
+ "Base64 Ordered DotSlash Encoding - Length: " . $i
+ );
+
+ $enc = Base64UrlSafe::encode($rand);
+ $this->assertSame(
+ \strtr(\base64_encode($rand), '+/', '-_'),
+ $enc
+ );
+ $this->assertSame(
+ $rand,
+ Base64UrlSafe::decode($enc)
+ );
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Hex;
+
+class HexTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Hex::encode()
+ * @covers Hex::decode()
+ * @covers Hex::encodeUpper()
+ */
+ public function testRandom()
+ {
+ for ($i = 1; $i < 32; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ $random = \random_bytes($i);
+
+ $enc = Hex::encode($random);
+ $this->assertSame(
+ $random,
+ Hex::decode($enc)
+ );
+ $this->assertSame(
+ \bin2hex($random),
+ $enc
+ );
+
+ $enc = Hex::encodeUpper($random);
+ $this->assertSame(
+ $random,
+ Hex::decode($enc)
+ );
+ $this->assertSame(
+ \strtoupper(\bin2hex($random)),
+ $enc
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+use \ParagonIE\ConstantTime\Base32;
+use \ParagonIE\ConstantTime\Base32Hex;
+use \ParagonIE\ConstantTime\Base64;
+use \ParagonIE\ConstantTime\Base64DotSlash;
+use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
+use \ParagonIE\ConstantTime\Encoding;
+use \ParagonIE\ConstantTime\Hex;
+
+/**
+ * Class RFC4648Test
+ *
+ * @ref https://tools.ietf.org/html/rfc4648#section-10
+ */
+class RFC4648Test extends PHPUnit_Framework_TestCase
+{
+ public function testVectorBase64()
+ {
+ $this->assertSame(Base64::encode(''), '');
+ $this->assertSame(Base64::encode('f'), 'Zg==');
+ $this->assertSame(Base64::encode('fo'), 'Zm8=');
+ $this->assertSame(Base64::encode('foo'), 'Zm9v');
+ $this->assertSame(Base64::encode('foob'), 'Zm9vYg==');
+ $this->assertSame(Base64::encode('fooba'), 'Zm9vYmE=');
+ $this->assertSame(Base64::encode('foobar'), 'Zm9vYmFy');
+ }
+
+ public function testVectorBase32()
+ {
+ $this->assertSame(Base32::encode(''), '');
+ $this->assertSame(Base32::encode('f'), 'my======');
+ $this->assertSame(Base32::encode('fo'), 'mzxq====');
+ $this->assertSame(Base32::encode('foo'), 'mzxw6===');
+ $this->assertSame(Base32::encode('foob'), 'mzxw6yq=');
+ $this->assertSame(Base32::encode('fooba'), 'mzxw6ytb');
+ $this->assertSame(Base32::encode('foobar'), 'mzxw6ytboi======');
+
+ $this->assertSame(Base32::encodeUpper(''), '');
+ $this->assertSame(Base32::encodeUpper('f'), 'MY======');
+ $this->assertSame(Base32::encodeUpper('fo'), 'MZXQ====');
+ $this->assertSame(Base32::encodeUpper('foo'), 'MZXW6===');
+ $this->assertSame(Base32::encodeUpper('foob'), 'MZXW6YQ=');
+ $this->assertSame(Base32::encodeUpper('fooba'), 'MZXW6YTB');
+ $this->assertSame(Base32::encodeUpper('foobar'), 'MZXW6YTBOI======');
+ }
+
+ public function testVectorBase32Hex()
+ {
+ $this->assertSame(Base32Hex::encode(''), '');
+ $this->assertSame(Base32Hex::encode('f'), 'co======');
+ $this->assertSame(Base32Hex::encode('fo'), 'cpng====');
+ $this->assertSame(Base32Hex::encode('foo'), 'cpnmu===');
+ $this->assertSame(Base32Hex::encode('foob'), 'cpnmuog=');
+ $this->assertSame(Base32Hex::encode('fooba'), 'cpnmuoj1');
+ $this->assertSame(Base32Hex::encode('foobar'), 'cpnmuoj1e8======');
+
+ $this->assertSame(Base32Hex::encodeUpper(''), '');
+ $this->assertSame(Base32Hex::encodeUpper('f'), 'CO======');
+ $this->assertSame(Base32Hex::encodeUpper('fo'), 'CPNG====');
+ $this->assertSame(Base32Hex::encodeUpper('foo'), 'CPNMU===');
+ $this->assertSame(Base32Hex::encodeUpper('foob'), 'CPNMUOG=');
+ $this->assertSame(Base32Hex::encodeUpper('fooba'), 'CPNMUOJ1');
+ $this->assertSame(Base32Hex::encodeUpper('foobar'), 'CPNMUOJ1E8======');
+ }
+
+ public function testVectorBase16()
+ {
+ $this->assertSame(Hex::encode(''), '');
+ $this->assertSame(Hex::encode('f'), '66');
+ $this->assertSame(Hex::encode('fo'), '666f');
+ $this->assertSame(Hex::encode('foo'), '666f6f');
+ $this->assertSame(Hex::encode('foob'), '666f6f62');
+ $this->assertSame(Hex::encode('fooba'), '666f6f6261');
+ $this->assertSame(Hex::encode('foobar'), '666f6f626172');
+
+ $this->assertSame(Hex::encodeUpper(''), '');
+ $this->assertSame(Hex::encodeUpper('f'), '66');
+ $this->assertSame(Hex::encodeUpper('fo'), '666F');
+ $this->assertSame(Hex::encodeUpper('foo'), '666F6F');
+ $this->assertSame(Hex::encodeUpper('foob'), '666F6F62');
+ $this->assertSame(Hex::encodeUpper('fooba'), '666F6F6261');
+ $this->assertSame(Hex::encodeUpper('foobar'), '666F6F626172');
+ }
+}
--- /dev/null
+<?php
+require_once __DIR__ . '/../vendor/autoload.php';
+
+define('ParagonIE\ConstantTime\true', false);
+define('ParagonIE\ConstantTime\false', true);
+define('ParagonIE\ConstantTime\null', true);
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) 2015 Paragon Initiative Enterprises
-
-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.
-
+++ /dev/null
-#!/usr/bin/env bash
-
-basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) )
-
-php -dphar.readonly=0 "$basedir/other/build_phar.php" $*
\ No newline at end of file
+++ /dev/null
-{
- "name": "paragonie/random_compat",
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
- "keywords": [
- "csprng",
- "random",
- "polyfill",
- "pseudorandom"
- ],
- "license": "MIT",
- "type": "library",
- "authors": [
- {
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
- }
- ],
- "support": {
- "issues": "https://github.com/paragonie/random_compat/issues",
- "email": "info@paragonie.com",
- "source": "https://github.com/paragonie/random_compat"
- },
- "require": {
- "php": "^7"
- },
- "require-dev": {
- "vimeo/psalm": "^1",
- "phpunit/phpunit": "4.*|5.*"
- },
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * @version 2.99.99
- * @released 2018-06-06
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-// NOP
+++ /dev/null
-<?php
-$dist = dirname(__DIR__).'/dist';
-if (!is_dir($dist)) {
- mkdir($dist, 0755);
-}
-if (file_exists($dist.'/random_compat.phar')) {
- unlink($dist.'/random_compat.phar');
-}
-$phar = new Phar(
- $dist.'/random_compat.phar',
- FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME,
- 'random_compat.phar'
-);
-rename(
- dirname(__DIR__).'/lib/random.php',
- dirname(__DIR__).'/lib/index.php'
-);
-$phar->buildFromDirectory(dirname(__DIR__).'/lib');
-rename(
- dirname(__DIR__).'/lib/index.php',
- dirname(__DIR__).'/lib/random.php'
-);
-
-/**
- * If we pass an (optional) path to a private key as a second argument, we will
- * sign the Phar with OpenSSL.
- *
- * If you leave this out, it will produce an unsigned .phar!
- */
-if ($argc > 1) {
- if (!@is_readable($argv[1])) {
- echo 'Could not read the private key file:', $argv[1], "\n";
- exit(255);
- }
- $pkeyFile = file_get_contents($argv[1]);
-
- $private = openssl_get_privatekey($pkeyFile);
- if ($private !== false) {
- $pkey = '';
- openssl_pkey_export($private, $pkey);
- $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
-
- /**
- * Save the corresponding public key to the file
- */
- if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
- $details = openssl_pkey_get_details($private);
- file_put_contents(
- $dist.'/random_compat.phar.pubkey',
- $details['key']
- );
- }
- } else {
- echo 'An error occurred reading the private key from OpenSSL.', "\n";
- exit(255);
- }
-}
+++ /dev/null
-<?php
-
-require_once 'lib/byte_safe_strings.php';
-require_once 'lib/cast_to_int.php';
-require_once 'lib/error_polyfill.php';
-require_once 'other/ide_stubs/libsodium.php';
-require_once 'lib/random.php';
-
-$int = random_int(0, 65536);
+++ /dev/null
-<?xml version="1.0"?>
-<psalm
- autoloader="psalm-autoload.php"
- stopOnFirstError="false"
- useDocblockTypes="true"
->
- <projectFiles>
- <directory name="lib" />
- </projectFiles>
- <issueHandlers>
- <RedundantConditionGivenDocblockType errorLevel="info" />
- <UnresolvableInclude errorLevel="info" />
- <DuplicateClass errorLevel="info" />
- <InvalidOperand errorLevel="info" />
- <UndefinedConstant errorLevel="info" />
- <MissingReturnType errorLevel="info" />
- <InvalidReturnType errorLevel="info" />
- </issueHandlers>
-</psalm>
--- /dev/null
+phpseclib Lead Developer: TerraFrost (Jim Wigginton)
+
+phpseclib Developers: monnerat (Patrick Monnerat)
+ bantu (Andreas Fischer)
+ petrich (Hans-Jürgen Petrich)
+ GrahamCampbell (Graham Campbell)
--- /dev/null
+Copyright 2007-2016 TerraFrost and other contributors
+http://phpseclib.sourceforge.net/
+
+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.
--- /dev/null
+# phpseclib - PHP Secure Communications Library
+
+[](https://travis-ci.org/phpseclib/phpseclib)
+
+MIT-licensed pure-PHP implementations of an arbitrary-precision integer
+arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
+AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
+
+* [Browse Git](https://github.com/phpseclib/phpseclib)
+* [Code Coverage Report](https://coverage.phpseclib.org/2.0/latest/)
+
+## Documentation
+
+* [Documentation / Manual](http://phpseclib.sourceforge.net/)
+* [API Documentation](https://api.phpseclib.org/2.0/) (generated by Sami)
+
+## Branches
+
+### master
+
+* Development Branch
+* Unstable API
+* Do not use in production
+
+### 2.0
+
+* Long term support (LTS) release
+* Modernized version of 1.0
+* Minimum PHP version: 5.3.3
+* PSR-4 autoloading with namespace rooted at `\phpseclib`
+* Install via Composer: `composer require phpseclib/phpseclib ~2.0`
+
+### 1.0
+
+* Long term support (LTS) release
+* PHP4 compatible
+* Composer compatible (PSR-0 autoloading)
+* Install using Composer: `composer require phpseclib/phpseclib ~1.0`
+* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
+* [Download 1.0.16 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.16.zip/download)
+
+## Support
+
+Need Support?
+
+* [Checkout Questions and Answers on Stack Overflow](http://stackoverflow.com/questions/tagged/phpseclib)
+* [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new)
+* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use)
+
+## Contributing
+
+1. Fork the Project
+
+2. Ensure you have Composer installed (see [Composer Download Instructions](https://getcomposer.org/download/))
+
+3. Install Development Dependencies
+
+ ``` sh
+ composer install
+ ```
+
+4. Create a Feature Branch
+
+5. (Recommended) Run the Test Suite
+
+ ``` sh
+ vendor/bin/phpunit
+ ```
+6. (Recommended) Check whether your code conforms to our Coding Standards by running
+
+ ``` sh
+ vendor/bin/phing -f build/build.xml sniff
+ ```
+
+7. Send us a Pull Request
--- /dev/null
+build: false
+shallow_clone: false
+platform:
+ - x86
+ - x64
+clone_folder: C:\projects\phpseclib
+
+install:
+ - cinst -y OpenSSL.Light
+ - SET PATH=C:\Program Files\OpenSSL;%PATH%
+ - sc config wuauserv start= auto
+ - net start wuauserv
+ - cinst -y php --version 5.6.30
+ - cd c:\tools\php56
+ - copy php.ini-production php.ini
+ - echo date.timezone="UTC" >> php.ini
+ - echo extension_dir=ext >> php.ini
+ - echo extension=php_openssl.dll >> php.ini
+ - echo extension=php_gmp.dll >> php.ini
+ - cd C:\projects\phpseclib
+ - SET PATH=C:\tools\php56;%PATH%
+ - php.exe -r "readfile('http://getcomposer.org/installer');" | php.exe
+ - php.exe composer.phar install --prefer-source --no-interaction
+
+test_script:
+ - cd C:\projects\phpseclib
+ - vendor\bin\phpunit.bat tests/Windows32Test.php
\ No newline at end of file
--- /dev/null
+{
+ "name": "phpseclib/phpseclib",
+ "type": "library",
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "keywords": [
+ "security",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "signature",
+ "signing",
+ "rsa",
+ "aes",
+ "blowfish",
+ "twofish",
+ "ssh",
+ "sftp",
+ "x509",
+ "x.509",
+ "asn1",
+ "asn.1",
+ "BigInteger"
+ ],
+ "homepage": "http://phpseclib.sourceforge.net",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phing/phing": "~2.7",
+ "phpunit/phpunit": "^4.8.35|^5.7|^6.0",
+ "sami/sami": "~2.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "suggest": {
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations."
+ },
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib\\": "phpseclib/"
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of AES.
+ *
+ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
+ * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
+ * to save one include_once().
+ *
+ * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
+ * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
+ * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
+ * is called, again, at which point, it'll be recalculated.
+ *
+ * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
+ * make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
+ * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $aes = new \phpseclib\Crypt\AES();
+ *
+ * $aes->setKey('abcdefghijklmnop');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $aes->decrypt($aes->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package AES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2008 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of AES.
+ *
+ * @package AES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class AES extends Rijndael
+{
+ /**
+ * Dummy function
+ *
+ * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
+ *
+ * @see \phpseclib\Crypt\Rijndael::setBlockLength()
+ * @access public
+ * @param int $length
+ */
+ function setBlockLength($length)
+ {
+ return;
+ }
+
+ /**
+ * Sets the key length
+ *
+ * Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
+ *
+ * @see \phpseclib\Crypt\Rijndael:setKeyLength()
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ switch ($length) {
+ case 160:
+ $length = 192;
+ break;
+ case 224:
+ $length = 256;
+ }
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Sets the key.
+ *
+ * Rijndael supports five different key lengths, AES only supports three.
+ *
+ * @see \phpseclib\Crypt\Rijndael:setKey()
+ * @see setKeyLength()
+ * @access public
+ * @param string $key
+ */
+ function setKey($key)
+ {
+ parent::setKey($key);
+
+ if (!$this->explicit_key_length) {
+ $length = strlen($key);
+ switch (true) {
+ case $length <= 16:
+ $this->key_length = 16;
+ break;
+ case $length <= 24:
+ $this->key_length = 24;
+ break;
+ default:
+ $this->key_length = 32;
+ }
+ $this->_setEngine();
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Base Class for all \phpseclib\Crypt\* cipher classes
+ *
+ * PHP version 5
+ *
+ * Internally for phpseclib developers:
+ * If you plan to add a new cipher class, please note following rules:
+ *
+ * - The new \phpseclib\Crypt\* cipher class should extend \phpseclib\Crypt\Base
+ *
+ * - Following methods are then required to be overridden/overloaded:
+ *
+ * - _encryptBlock()
+ *
+ * - _decryptBlock()
+ *
+ * - _setupKey()
+ *
+ * - All other methods are optional to be overridden/overloaded
+ *
+ * - Look at the source code of the current ciphers how they extend \phpseclib\Crypt\Base
+ * and take one of them as a start up for the new cipher class.
+ *
+ * - Please read all the other comments/notes/hints here also for each class var/method
+ *
+ * @category Crypt
+ * @package Base
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Base Class for all \phpseclib\Crypt\* cipher classes
+ *
+ * @package Base
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ */
+abstract class Base
+{
+ /**#@+
+ * @access public
+ * @see \phpseclib\Crypt\Base::encrypt()
+ * @see \phpseclib\Crypt\Base::decrypt()
+ */
+ /**
+ * Encrypt / decrypt using the Counter mode.
+ *
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
+ */
+ const MODE_CTR = -1;
+ /**
+ * Encrypt / decrypt using the Electronic Code Book mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
+ */
+ const MODE_ECB = 1;
+ /**
+ * Encrypt / decrypt using the Code Book Chaining mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
+ */
+ const MODE_CBC = 2;
+ /**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
+ */
+ const MODE_CFB = 3;
+ /**
+ * Encrypt / decrypt using the Cipher Feedback mode (8bit)
+ */
+ const MODE_CFB8 = 38;
+ /**
+ * Encrypt / decrypt using the Output Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
+ */
+ const MODE_OFB = 4;
+ /**
+ * Encrypt / decrypt using streaming mode.
+ */
+ const MODE_STREAM = 5;
+ /**#@-*/
+
+ /**
+ * Whirlpool available flag
+ *
+ * @see \phpseclib\Crypt\Base::_hashInlineCryptFunction()
+ * @var bool
+ * @access private
+ */
+ static $WHIRLPOOL_AVAILABLE;
+
+ /**#@+
+ * @access private
+ * @see \phpseclib\Crypt\Base::__construct()
+ */
+ /**
+ * Base value for the internal implementation $engine switch
+ */
+ const ENGINE_INTERNAL = 1;
+ /**
+ * Base value for the mcrypt implementation $engine switch
+ */
+ const ENGINE_MCRYPT = 2;
+ /**
+ * Base value for the mcrypt implementation $engine switch
+ */
+ const ENGINE_OPENSSL = 3;
+ /**#@-*/
+
+ /**
+ * The Encryption Mode
+ *
+ * @see self::__construct()
+ * @var int
+ * @access private
+ */
+ var $mode;
+
+ /**
+ * The Block Length of the block cipher
+ *
+ * @var int
+ * @access private
+ */
+ var $block_size = 16;
+
+ /**
+ * The Key
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+ /**
+ * The Initialization Vector
+ *
+ * @see self::setIV()
+ * @var string
+ * @access private
+ */
+ var $iv;
+
+ /**
+ * A "sliding" Initialization Vector
+ *
+ * @see self::enableContinuousBuffer()
+ * @see self::_clearBuffers()
+ * @var string
+ * @access private
+ */
+ var $encryptIV;
+
+ /**
+ * A "sliding" Initialization Vector
+ *
+ * @see self::enableContinuousBuffer()
+ * @see self::_clearBuffers()
+ * @var string
+ * @access private
+ */
+ var $decryptIV;
+
+ /**
+ * Continuous Buffer status
+ *
+ * @see self::enableContinuousBuffer()
+ * @var bool
+ * @access private
+ */
+ var $continuousBuffer = false;
+
+ /**
+ * Encryption buffer for CTR, OFB and CFB modes
+ *
+ * @see self::encrypt()
+ * @see self::_clearBuffers()
+ * @var array
+ * @access private
+ */
+ var $enbuffer;
+
+ /**
+ * Decryption buffer for CTR, OFB and CFB modes
+ *
+ * @see self::decrypt()
+ * @see self::_clearBuffers()
+ * @var array
+ * @access private
+ */
+ var $debuffer;
+
+ /**
+ * mcrypt resource for encryption
+ *
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
+ *
+ * @see self::encrypt()
+ * @var resource
+ * @access private
+ */
+ var $enmcrypt;
+
+ /**
+ * mcrypt resource for decryption
+ *
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
+ *
+ * @see self::decrypt()
+ * @var resource
+ * @access private
+ */
+ var $demcrypt;
+
+ /**
+ * Does the enmcrypt resource need to be (re)initialized?
+ *
+ * @see \phpseclib\Crypt\Twofish::setKey()
+ * @see \phpseclib\Crypt\Twofish::setIV()
+ * @var bool
+ * @access private
+ */
+ var $enchanged = true;
+
+ /**
+ * Does the demcrypt resource need to be (re)initialized?
+ *
+ * @see \phpseclib\Crypt\Twofish::setKey()
+ * @see \phpseclib\Crypt\Twofish::setIV()
+ * @var bool
+ * @access private
+ */
+ var $dechanged = true;
+
+ /**
+ * mcrypt resource for CFB mode
+ *
+ * mcrypt's CFB mode, in (and only in) buffered context,
+ * is broken, so phpseclib implements the CFB mode by it self,
+ * even when the mcrypt php extension is available.
+ *
+ * In order to do the CFB-mode work (fast) phpseclib
+ * use a separate ECB-mode mcrypt resource.
+ *
+ * @link http://phpseclib.sourceforge.net/cfb-demo.phps
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @see self::_setupMcrypt()
+ * @var resource
+ * @access private
+ */
+ var $ecb;
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * Only relevant if $continuousBuffer enabled
+ * and $engine == self::ENGINE_MCRYPT
+ *
+ * It's faster to re-init $enmcrypt if
+ * $buffer bytes > $cfb_init_len than
+ * using the $ecb resource furthermore.
+ *
+ * This value depends of the chosen cipher
+ * and the time it would be needed for it's
+ * initialization [by mcrypt_generic_init()]
+ * which, typically, depends on the complexity
+ * on its internaly Key-expanding algorithm.
+ *
+ * @see self::encrypt()
+ * @var int
+ * @access private
+ */
+ var $cfb_init_len = 600;
+
+ /**
+ * Does internal cipher state need to be (re)initialized?
+ *
+ * @see self::setKey()
+ * @see self::setIV()
+ * @see self::disableContinuousBuffer()
+ * @var bool
+ * @access private
+ */
+ var $changed = true;
+
+ /**
+ * Padding status
+ *
+ * @see self::enablePadding()
+ * @var bool
+ * @access private
+ */
+ var $padding = true;
+
+ /**
+ * Is the mode one that is paddable?
+ *
+ * @see self::__construct()
+ * @var bool
+ * @access private
+ */
+ var $paddable = false;
+
+ /**
+ * Holds which crypt engine internaly should be use,
+ * which will be determined automatically on __construct()
+ *
+ * Currently available $engines are:
+ * - self::ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
+ * - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
+ * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
+ *
+ * @see self::_setEngine()
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @var int
+ * @access private
+ */
+ var $engine;
+
+ /**
+ * Holds the preferred crypt engine
+ *
+ * @see self::_setEngine()
+ * @see self::setPreferredEngine()
+ * @var int
+ * @access private
+ */
+ var $preferredEngine;
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * Only used if $engine == self::ENGINE_MCRYPT
+ *
+ * @link http://www.php.net/mcrypt_module_open
+ * @link http://www.php.net/mcrypt_list_algorithms
+ * @see self::_setupMcrypt()
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt;
+
+ /**
+ * The openssl specific name of the cipher
+ *
+ * Only used if $engine == self::ENGINE_OPENSSL
+ *
+ * @link http://www.php.net/openssl-get-cipher-methods
+ * @var string
+ * @access private
+ */
+ var $cipher_name_openssl;
+
+ /**
+ * The openssl specific name of the cipher in ECB mode
+ *
+ * If OpenSSL does not support the mode we're trying to use (CTR)
+ * it can still be emulated with ECB mode.
+ *
+ * @link http://www.php.net/openssl-get-cipher-methods
+ * @var string
+ * @access private
+ */
+ var $cipher_name_openssl_ecb;
+
+ /**
+ * The default salt used by setPassword()
+ *
+ * @see self::setPassword()
+ * @var string
+ * @access private
+ */
+ var $password_default_salt = 'phpseclib/salt';
+
+ /**
+ * The name of the performance-optimized callback function
+ *
+ * Used by encrypt() / decrypt()
+ * only if $engine == self::ENGINE_INTERNAL
+ *
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @see self::_setupInlineCrypt()
+ * @see self::$use_inline_crypt
+ * @var Callback
+ * @access private
+ */
+ var $inline_crypt;
+
+ /**
+ * Holds whether performance-optimized $inline_crypt() can/should be used.
+ *
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @see self::inline_crypt
+ * @var mixed
+ * @access private
+ */
+ var $use_inline_crypt;
+
+ /**
+ * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
+ *
+ * @see self::_openssl_ctr_process()
+ * @var bool
+ * @access private
+ */
+ var $openssl_emulate_ctr = false;
+
+ /**
+ * Determines what options are passed to openssl_encrypt/decrypt
+ *
+ * @see self::isValidEngine()
+ * @var mixed
+ * @access private
+ */
+ var $openssl_options;
+
+ /**
+ * Has the key length explicitly been set or should it be derived from the key, itself?
+ *
+ * @see self::setKeyLength()
+ * @var bool
+ * @access private
+ */
+ var $explicit_key_length = false;
+
+ /**
+ * Don't truncate / null pad key
+ *
+ * @see self::_clearBuffers()
+ * @var bool
+ * @access private
+ */
+ var $skip_key_adjustment = false;
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * $mode could be:
+ *
+ * - self::MODE_ECB
+ *
+ * - self::MODE_CBC
+ *
+ * - self::MODE_CTR
+ *
+ * - self::MODE_CFB
+ *
+ * - self::MODE_OFB
+ *
+ * If not explicitly set, self::MODE_CBC will be used.
+ *
+ * @param int $mode
+ * @access public
+ */
+ function __construct($mode = self::MODE_CBC)
+ {
+ // $mode dependent settings
+ switch ($mode) {
+ case self::MODE_ECB:
+ $this->paddable = true;
+ $this->mode = self::MODE_ECB;
+ break;
+ case self::MODE_CTR:
+ case self::MODE_CFB:
+ case self::MODE_CFB8:
+ case self::MODE_OFB:
+ case self::MODE_STREAM:
+ $this->mode = $mode;
+ break;
+ case self::MODE_CBC:
+ default:
+ $this->paddable = true;
+ $this->mode = self::MODE_CBC;
+ }
+
+ $this->_setEngine();
+
+ // Determining whether inline crypting can be used by the cipher
+ if ($this->use_inline_crypt !== false) {
+ $this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
+ }
+ }
+
+ /**
+ * Sets the initialization vector. (optional)
+ *
+ * SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. If not explicitly set, it'll be assumed
+ * to be all zero's.
+ *
+ * @access public
+ * @param string $iv
+ * @internal Can be overwritten by a sub class, but does not have to be
+ */
+ function setIV($iv)
+ {
+ if ($this->mode == self::MODE_ECB) {
+ return;
+ }
+
+ $this->iv = $iv;
+ $this->changed = true;
+ }
+
+ /**
+ * Sets the key length.
+ *
+ * Keys with explicitly set lengths need to be treated accordingly
+ *
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ $this->explicit_key_length = true;
+ $this->changed = true;
+ $this->_setEngine();
+ }
+
+ /**
+ * Returns the current key length in bits
+ *
+ * @access public
+ * @return int
+ */
+ function getKeyLength()
+ {
+ return $this->key_length << 3;
+ }
+
+ /**
+ * Returns the current block length in bits
+ *
+ * @access public
+ * @return int
+ */
+ function getBlockLength()
+ {
+ return $this->block_size << 3;
+ }
+
+ /**
+ * Sets the key.
+ *
+ * The min/max length(s) of the key depends on the cipher which is used.
+ * If the key not fits the length(s) of the cipher it will paded with null bytes
+ * up to the closest valid key length. If the key is more than max length,
+ * we trim the excess bits.
+ *
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
+ *
+ * @access public
+ * @param string $key
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function setKey($key)
+ {
+ if (!$this->explicit_key_length) {
+ $this->setKeyLength(strlen($key) << 3);
+ $this->explicit_key_length = false;
+ }
+
+ $this->key = $key;
+ $this->changed = true;
+ $this->_setEngine();
+ }
+
+ /**
+ * Sets the password.
+ *
+ * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
+ * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
+ * $hash, $salt, $count, $dkLen
+ *
+ * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
+ *
+ * @see Crypt/Hash.php
+ * @param string $password
+ * @param string $method
+ * @return bool
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function setPassword($password, $method = 'pbkdf2')
+ {
+ $key = '';
+
+ switch ($method) {
+ default: // 'pbkdf2' or 'pbkdf1'
+ $func_args = func_get_args();
+
+ // Hash function
+ $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
+
+ // WPA and WPA2 use the SSID as the salt
+ $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
+
+ // RFC2898#section-4.2 uses 1,000 iterations by default
+ // WPA and WPA2 use 4,096.
+ $count = isset($func_args[4]) ? $func_args[4] : 1000;
+
+ // Keylength
+ if (isset($func_args[5])) {
+ $dkLen = $func_args[5];
+ } else {
+ $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
+ }
+
+ switch (true) {
+ case $method == 'pbkdf1':
+ $hashObj = new Hash();
+ $hashObj->setHash($hash);
+ if ($dkLen > $hashObj->getLength()) {
+ user_error('Derived key too long');
+ return false;
+ }
+ $t = $password . $salt;
+ for ($i = 0; $i < $count; ++$i) {
+ $t = $hashObj->hash($t);
+ }
+ $key = substr($t, 0, $dkLen);
+
+ $this->setKey(substr($key, 0, $dkLen >> 1));
+ $this->setIV(substr($key, $dkLen >> 1));
+
+ return true;
+ // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
+ case !function_exists('hash_pbkdf2'):
+ case !function_exists('hash_algos'):
+ case !in_array($hash, hash_algos()):
+ $i = 1;
+ $hmac = new Hash();
+ $hmac->setHash($hash);
+ $hmac->setKey($password);
+ while (strlen($key) < $dkLen) {
+ $f = $u = $hmac->hash($salt . pack('N', $i++));
+ for ($j = 2; $j <= $count; ++$j) {
+ $u = $hmac->hash($u);
+ $f^= $u;
+ }
+ $key.= $f;
+ }
+ $key = substr($key, 0, $dkLen);
+ break;
+ default:
+ $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
+ }
+ }
+
+ $this->setKey($key);
+
+ return true;
+ }
+
+ /**
+ * Encrypts a message.
+ *
+ * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
+ * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
+ * necessary are discussed in the following
+ * URL:
+ *
+ * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
+ *
+ * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
+ * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
+ * length.
+ *
+ * @see self::decrypt()
+ * @access public
+ * @param string $plaintext
+ * @return string $ciphertext
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function encrypt($plaintext)
+ {
+ if ($this->paddable) {
+ $plaintext = $this->_pad($plaintext);
+ }
+
+ if ($this->engine === self::ENGINE_OPENSSL) {
+ if ($this->changed) {
+ $this->_clearBuffers();
+ $this->changed = false;
+ }
+ switch ($this->mode) {
+ case self::MODE_STREAM:
+ return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
+ case self::MODE_ECB:
+ $result = @openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
+ return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
+ case self::MODE_CBC:
+ $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
+ if (!defined('OPENSSL_RAW_DATA')) {
+ $result = substr($result, 0, -$this->block_size);
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = substr($result, -$this->block_size);
+ }
+ return $result;
+ case self::MODE_CTR:
+ return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
+ case self::MODE_CFB:
+ // cfb loosely routines inspired by openssl's:
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
+ $ciphertext = '';
+ if ($this->continuousBuffer) {
+ $iv = &$this->encryptIV;
+ $pos = &$this->enbuffer['pos'];
+ } else {
+ $iv = $this->encryptIV;
+ $pos = 0;
+ }
+ $len = strlen($plaintext);
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $this->block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
+ $plaintext = substr($plaintext, $i);
+ }
+
+ $overflow = $len % $this->block_size;
+
+ if ($overflow) {
+ $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
+ $iv = $this->_string_pop($ciphertext, $this->block_size);
+
+ $size = $len - $overflow;
+ $block = $iv ^ substr($plaintext, -$overflow);
+ $iv = substr_replace($iv, $block, 0, $overflow);
+ $ciphertext.= $block;
+ $pos = $overflow;
+ } elseif ($len) {
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
+ $iv = substr($ciphertext, -$this->block_size);
+ }
+
+ return $ciphertext;
+ case self::MODE_CFB8:
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
+ if ($this->continuousBuffer) {
+ if (($len = strlen($ciphertext)) >= $this->block_size) {
+ $this->encryptIV = substr($ciphertext, -$this->block_size);
+ } else {
+ $this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
+ }
+ }
+ return $ciphertext;
+ case self::MODE_OFB:
+ return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
+ }
+ }
+
+ if ($this->engine === self::ENGINE_MCRYPT) {
+ if ($this->changed) {
+ $this->_setupMcrypt();
+ $this->changed = false;
+ }
+ if ($this->enchanged) {
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
+ $this->enchanged = false;
+ }
+
+ // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
+ // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
+ // rewritten CFB implementation the above outputs the same thing twice.
+ if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
+ $block_size = $this->block_size;
+ $iv = &$this->encryptIV;
+ $pos = &$this->enbuffer['pos'];
+ $len = strlen($plaintext);
+ $ciphertext = '';
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
+ $this->enbuffer['enmcrypt_init'] = true;
+ }
+ if ($len >= $block_size) {
+ if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
+ if ($this->enbuffer['enmcrypt_init'] === true) {
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
+ $this->enbuffer['enmcrypt_init'] = false;
+ }
+ $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
+ $iv = substr($ciphertext, -$block_size);
+ $len%= $block_size;
+ } else {
+ while ($len >= $block_size) {
+ $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
+ $ciphertext.= $iv;
+ $len-= $block_size;
+ $i+= $block_size;
+ }
+ }
+ }
+
+ if ($len) {
+ $iv = @mcrypt_generic($this->ecb, $iv);
+ $block = $iv ^ substr($plaintext, -$len);
+ $iv = substr_replace($iv, $block, 0, $len);
+ $ciphertext.= $block;
+ $pos = $len;
+ }
+
+ return $ciphertext;
+ }
+
+ $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
+
+ if (!$this->continuousBuffer) {
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
+ }
+
+ return $ciphertext;
+ }
+
+ if ($this->changed) {
+ $this->_setup();
+ $this->changed = false;
+ }
+ if ($this->use_inline_crypt) {
+ $inline = $this->inline_crypt;
+ return $inline('encrypt', $this, $plaintext);
+ }
+
+ $buffer = &$this->enbuffer;
+ $block_size = $this->block_size;
+ $ciphertext = '';
+ switch ($this->mode) {
+ case self::MODE_ECB:
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
+ }
+ break;
+ case self::MODE_CBC:
+ $xor = $this->encryptIV;
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ $block = $this->_encryptBlock($block ^ $xor);
+ $xor = $block;
+ $ciphertext.= $block;
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = $xor;
+ }
+ break;
+ case self::MODE_CTR:
+ $xor = $this->encryptIV;
+ if (strlen($buffer['ciphertext'])) {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
+ $buffer['ciphertext'].= $this->_encryptBlock($xor);
+ }
+ $this->_increment_str($xor);
+ $key = $this->_string_shift($buffer['ciphertext'], $block_size);
+ $ciphertext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ $key = $this->_encryptBlock($xor);
+ $this->_increment_str($xor);
+ $ciphertext.= $block ^ $key;
+ }
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = $xor;
+ if ($start = strlen($plaintext) % $block_size) {
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
+ }
+ }
+ break;
+ case self::MODE_CFB:
+ // cfb loosely routines inspired by openssl's:
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
+ if ($this->continuousBuffer) {
+ $iv = &$this->encryptIV;
+ $pos = &$buffer['pos'];
+ } else {
+ $iv = $this->encryptIV;
+ $pos = 0;
+ }
+ $len = strlen($plaintext);
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
+ }
+ while ($len >= $block_size) {
+ $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
+ $ciphertext.= $iv;
+ $len-= $block_size;
+ $i+= $block_size;
+ }
+ if ($len) {
+ $iv = $this->_encryptBlock($iv);
+ $block = $iv ^ substr($plaintext, $i);
+ $iv = substr_replace($iv, $block, 0, $len);
+ $ciphertext.= $block;
+ $pos = $len;
+ }
+ break;
+ case self::MODE_CFB8:
+ $ciphertext = '';
+ $len = strlen($plaintext);
+ $iv = $this->encryptIV;
+
+ for ($i = 0; $i < $len; ++$i) {
+ $ciphertext .= ($c = $plaintext[$i] ^ $this->_encryptBlock($iv));
+ $iv = substr($iv, 1) . $c;
+ }
+
+ if ($this->continuousBuffer) {
+ if ($len >= $block_size) {
+ $this->encryptIV = substr($ciphertext, -$block_size);
+ } else {
+ $this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len);
+ }
+ }
+ break;
+ case self::MODE_OFB:
+ $xor = $this->encryptIV;
+ if (strlen($buffer['xor'])) {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['xor'])) {
+ $xor = $this->_encryptBlock($xor);
+ $buffer['xor'].= $xor;
+ }
+ $key = $this->_string_shift($buffer['xor'], $block_size);
+ $ciphertext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $xor = $this->_encryptBlock($xor);
+ $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
+ }
+ $key = $xor;
+ }
+ if ($this->continuousBuffer) {
+ $this->encryptIV = $xor;
+ if ($start = strlen($plaintext) % $block_size) {
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
+ }
+ }
+ break;
+ case self::MODE_STREAM:
+ $ciphertext = $this->_encryptBlock($plaintext);
+ break;
+ }
+
+ return $ciphertext;
+ }
+
+ /**
+ * Decrypts a message.
+ *
+ * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
+ * it is.
+ *
+ * @see self::encrypt()
+ * @access public
+ * @param string $ciphertext
+ * @return string $plaintext
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function decrypt($ciphertext)
+ {
+ if ($this->paddable) {
+ // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
+ // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
+ $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
+ }
+
+ if ($this->engine === self::ENGINE_OPENSSL) {
+ if ($this->changed) {
+ $this->_clearBuffers();
+ $this->changed = false;
+ }
+ switch ($this->mode) {
+ case self::MODE_STREAM:
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
+ break;
+ case self::MODE_ECB:
+ if (!defined('OPENSSL_RAW_DATA')) {
+ $ciphertext.= @openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
+ }
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
+ break;
+ case self::MODE_CBC:
+ if (!defined('OPENSSL_RAW_DATA')) {
+ $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
+ $ciphertext.= substr(@openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
+ $offset = 2 * $this->block_size;
+ } else {
+ $offset = $this->block_size;
+ }
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
+ if ($this->continuousBuffer) {
+ $this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
+ }
+ break;
+ case self::MODE_CTR:
+ $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
+ break;
+ case self::MODE_CFB:
+ // cfb loosely routines inspired by openssl's:
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
+ $plaintext = '';
+ if ($this->continuousBuffer) {
+ $iv = &$this->decryptIV;
+ $pos = &$this->buffer['pos'];
+ } else {
+ $iv = $this->decryptIV;
+ $pos = 0;
+ }
+ $len = strlen($ciphertext);
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $this->block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
+ $ciphertext = substr($ciphertext, $i);
+ }
+ $overflow = $len % $this->block_size;
+ if ($overflow) {
+ $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
+ if ($len - $overflow) {
+ $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
+ }
+ $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
+ $plaintext.= $iv ^ substr($ciphertext, -$overflow);
+ $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
+ $pos = $overflow;
+ } elseif ($len) {
+ $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
+ $iv = substr($ciphertext, -$this->block_size);
+ }
+ break;
+ case self::MODE_CFB8:
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
+ if ($this->continuousBuffer) {
+ if (($len = strlen($ciphertext)) >= $this->block_size) {
+ $this->decryptIV = substr($ciphertext, -$this->block_size);
+ } else {
+ $this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
+ }
+ }
+ break;
+ case self::MODE_OFB:
+ $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
+ }
+
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
+ }
+
+ if ($this->engine === self::ENGINE_MCRYPT) {
+ $block_size = $this->block_size;
+ if ($this->changed) {
+ $this->_setupMcrypt();
+ $this->changed = false;
+ }
+ if ($this->dechanged) {
+ @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
+ $this->dechanged = false;
+ }
+
+ if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
+ $iv = &$this->decryptIV;
+ $pos = &$this->debuffer['pos'];
+ $len = strlen($ciphertext);
+ $plaintext = '';
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
+ }
+ if ($len >= $block_size) {
+ $cb = substr($ciphertext, $i, $len - $len % $block_size);
+ $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
+ $iv = substr($cb, -$block_size);
+ $len%= $block_size;
+ }
+ if ($len) {
+ $iv = @mcrypt_generic($this->ecb, $iv);
+ $plaintext.= $iv ^ substr($ciphertext, -$len);
+ $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
+ $pos = $len;
+ }
+
+ return $plaintext;
+ }
+
+ $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
+
+ if (!$this->continuousBuffer) {
+ @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
+ }
+
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
+ }
+
+ if ($this->changed) {
+ $this->_setup();
+ $this->changed = false;
+ }
+ if ($this->use_inline_crypt) {
+ $inline = $this->inline_crypt;
+ return $inline('decrypt', $this, $ciphertext);
+ }
+
+ $block_size = $this->block_size;
+
+ $buffer = &$this->debuffer;
+ $plaintext = '';
+ switch ($this->mode) {
+ case self::MODE_ECB:
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
+ }
+ break;
+ case self::MODE_CBC:
+ $xor = $this->decryptIV;
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ $plaintext.= $this->_decryptBlock($block) ^ $xor;
+ $xor = $block;
+ }
+ if ($this->continuousBuffer) {
+ $this->decryptIV = $xor;
+ }
+ break;
+ case self::MODE_CTR:
+ $xor = $this->decryptIV;
+ if (strlen($buffer['ciphertext'])) {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
+ $buffer['ciphertext'].= $this->_encryptBlock($xor);
+ $this->_increment_str($xor);
+ }
+ $key = $this->_string_shift($buffer['ciphertext'], $block_size);
+ $plaintext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ $key = $this->_encryptBlock($xor);
+ $this->_increment_str($xor);
+ $plaintext.= $block ^ $key;
+ }
+ }
+ if ($this->continuousBuffer) {
+ $this->decryptIV = $xor;
+ if ($start = strlen($ciphertext) % $block_size) {
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
+ }
+ }
+ break;
+ case self::MODE_CFB:
+ if ($this->continuousBuffer) {
+ $iv = &$this->decryptIV;
+ $pos = &$buffer['pos'];
+ } else {
+ $iv = $this->decryptIV;
+ $pos = 0;
+ }
+ $len = strlen($ciphertext);
+ $i = 0;
+ if ($pos) {
+ $orig_pos = $pos;
+ $max = $block_size - $pos;
+ if ($len >= $max) {
+ $i = $max;
+ $len-= $max;
+ $pos = 0;
+ } else {
+ $i = $len;
+ $pos+= $len;
+ $len = 0;
+ }
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
+ }
+ while ($len >= $block_size) {
+ $iv = $this->_encryptBlock($iv);
+ $cb = substr($ciphertext, $i, $block_size);
+ $plaintext.= $iv ^ $cb;
+ $iv = $cb;
+ $len-= $block_size;
+ $i+= $block_size;
+ }
+ if ($len) {
+ $iv = $this->_encryptBlock($iv);
+ $plaintext.= $iv ^ substr($ciphertext, $i);
+ $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
+ $pos = $len;
+ }
+ break;
+ case self::MODE_CFB8:
+ $plaintext = '';
+ $len = strlen($ciphertext);
+ $iv = $this->decryptIV;
+
+ for ($i = 0; $i < $len; ++$i) {
+ $plaintext .= $ciphertext[$i] ^ $this->_encryptBlock($iv);
+ $iv = substr($iv, 1) . $ciphertext[$i];
+ }
+
+ if ($this->continuousBuffer) {
+ if ($len >= $block_size) {
+ $this->decryptIV = substr($ciphertext, -$block_size);
+ } else {
+ $this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len);
+ }
+ }
+ break;
+ case self::MODE_OFB:
+ $xor = $this->decryptIV;
+ if (strlen($buffer['xor'])) {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $block = substr($ciphertext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['xor'])) {
+ $xor = $this->_encryptBlock($xor);
+ $buffer['xor'].= $xor;
+ }
+ $key = $this->_string_shift($buffer['xor'], $block_size);
+ $plaintext.= $block ^ $key;
+ }
+ } else {
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
+ $xor = $this->_encryptBlock($xor);
+ $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
+ }
+ $key = $xor;
+ }
+ if ($this->continuousBuffer) {
+ $this->decryptIV = $xor;
+ if ($start = strlen($ciphertext) % $block_size) {
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
+ }
+ }
+ break;
+ case self::MODE_STREAM:
+ $plaintext = $this->_decryptBlock($ciphertext);
+ break;
+ }
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
+ }
+
+ /**
+ * OpenSSL CTR Processor
+ *
+ * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
+ * for CTR is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
+ * and Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
+ * function will emulate CTR with ECB when necessary.
+ *
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @param string $plaintext
+ * @param string $encryptIV
+ * @param array $buffer
+ * @return string
+ * @access private
+ */
+ function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
+ {
+ $ciphertext = '';
+
+ $block_size = $this->block_size;
+ $key = $this->key;
+
+ if ($this->openssl_emulate_ctr) {
+ $xor = $encryptIV;
+ if (strlen($buffer['ciphertext'])) {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
+ $result = @openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
+ $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
+ $buffer['ciphertext'].= $result;
+ }
+ $this->_increment_str($xor);
+ $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
+ $ciphertext.= $block ^ $otp;
+ }
+ } else {
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
+ $block = substr($plaintext, $i, $block_size);
+ $otp = @openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
+ $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
+ $this->_increment_str($xor);
+ $ciphertext.= $block ^ $otp;
+ }
+ }
+ if ($this->continuousBuffer) {
+ $encryptIV = $xor;
+ if ($start = strlen($plaintext) % $block_size) {
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
+ }
+ }
+
+ return $ciphertext;
+ }
+
+ if (strlen($buffer['ciphertext'])) {
+ $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
+ $plaintext = substr($plaintext, strlen($ciphertext));
+
+ if (!strlen($plaintext)) {
+ return $ciphertext;
+ }
+ }
+
+ $overflow = strlen($plaintext) % $block_size;
+ if ($overflow) {
+ $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
+ $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
+ $temp = $this->_string_pop($encrypted, $block_size);
+ $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
+ if ($this->continuousBuffer) {
+ $buffer['ciphertext'] = substr($temp, $overflow);
+ $encryptIV = $temp;
+ }
+ } elseif (!strlen($buffer['ciphertext'])) {
+ $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
+ $temp = $this->_string_pop($ciphertext, $block_size);
+ if ($this->continuousBuffer) {
+ $encryptIV = $temp;
+ }
+ }
+ if ($this->continuousBuffer) {
+ if (!defined('OPENSSL_RAW_DATA')) {
+ $encryptIV.= @openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
+ }
+ $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
+ if ($overflow) {
+ $this->_increment_str($encryptIV);
+ }
+ }
+
+ return $ciphertext;
+ }
+
+ /**
+ * OpenSSL OFB Processor
+ *
+ * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
+ * for OFB is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
+ * and Base::decrypt().
+ *
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @param string $plaintext
+ * @param string $encryptIV
+ * @param array $buffer
+ * @return string
+ * @access private
+ */
+ function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
+ {
+ if (strlen($buffer['xor'])) {
+ $ciphertext = $plaintext ^ $buffer['xor'];
+ $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
+ $plaintext = substr($plaintext, strlen($ciphertext));
+ } else {
+ $ciphertext = '';
+ }
+
+ $block_size = $this->block_size;
+
+ $len = strlen($plaintext);
+ $key = $this->key;
+ $overflow = $len % $block_size;
+
+ if (strlen($plaintext)) {
+ if ($overflow) {
+ $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
+ $xor = $this->_string_pop($ciphertext, $block_size);
+ if ($this->continuousBuffer) {
+ $encryptIV = $xor;
+ }
+ $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
+ if ($this->continuousBuffer) {
+ $buffer['xor'] = $xor;
+ }
+ } else {
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
+ if ($this->continuousBuffer) {
+ $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
+ }
+ }
+ }
+
+ return $ciphertext;
+ }
+
+ /**
+ * phpseclib <-> OpenSSL Mode Mapper
+ *
+ * May need to be overwritten by classes extending this one in some cases
+ *
+ * @return int
+ * @access private
+ */
+ function _openssl_translate_mode()
+ {
+ switch ($this->mode) {
+ case self::MODE_ECB:
+ return 'ecb';
+ case self::MODE_CBC:
+ return 'cbc';
+ case self::MODE_CTR:
+ return 'ctr';
+ case self::MODE_CFB:
+ return 'cfb';
+ case self::MODE_CFB8:
+ return 'cfb8';
+ case self::MODE_OFB:
+ return 'ofb';
+ }
+ }
+
+ /**
+ * Pad "packets".
+ *
+ * Block ciphers working by encrypting between their specified [$this->]block_size at a time
+ * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
+ * pad the input so that it is of the proper length.
+ *
+ * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
+ * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
+ * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
+ * transmitted separately)
+ *
+ * @see self::disablePadding()
+ * @access public
+ */
+ function enablePadding()
+ {
+ $this->padding = true;
+ }
+
+ /**
+ * Do not pad packets.
+ *
+ * @see self::enablePadding()
+ * @access public
+ */
+ function disablePadding()
+ {
+ $this->padding = false;
+ }
+
+ /**
+ * Treat consecutive "packets" as if they are a continuous buffer.
+ *
+ * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
+ * will yield different outputs:
+ *
+ * <code>
+ * echo $rijndael->encrypt(substr($plaintext, 0, 16));
+ * echo $rijndael->encrypt(substr($plaintext, 16, 16));
+ * </code>
+ * <code>
+ * echo $rijndael->encrypt($plaintext);
+ * </code>
+ *
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
+ * another, as demonstrated with the following:
+ *
+ * <code>
+ * $rijndael->encrypt(substr($plaintext, 0, 16));
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
+ * </code>
+ * <code>
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
+ * </code>
+ *
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
+ *
+ * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() object changes after each
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
+ * however, they are also less intuitive and more likely to cause you problems.
+ *
+ * @see self::disableContinuousBuffer()
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function enableContinuousBuffer()
+ {
+ if ($this->mode == self::MODE_ECB) {
+ return;
+ }
+
+ $this->continuousBuffer = true;
+
+ $this->_setEngine();
+ }
+
+ /**
+ * Treat consecutive packets as if they are a discontinuous buffer.
+ *
+ * The default behavior.
+ *
+ * @see self::enableContinuousBuffer()
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function disableContinuousBuffer()
+ {
+ if ($this->mode == self::MODE_ECB) {
+ return;
+ }
+ if (!$this->continuousBuffer) {
+ return;
+ }
+
+ $this->continuousBuffer = false;
+ $this->changed = true;
+
+ $this->_setEngine();
+ }
+
+ /**
+ * Test for engine validity
+ *
+ * @see self::__construct()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ switch ($engine) {
+ case self::ENGINE_OPENSSL:
+ if ($this->mode == self::MODE_STREAM && $this->continuousBuffer) {
+ return false;
+ }
+ $this->openssl_emulate_ctr = false;
+ $result = $this->cipher_name_openssl &&
+ extension_loaded('openssl') &&
+ // PHP 5.3.0 - 5.3.2 did not let you set IV's
+ version_compare(PHP_VERSION, '5.3.3', '>=');
+ if (!$result) {
+ return false;
+ }
+
+ // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
+ // $options openssl_encrypt expected a boolean $raw_data.
+ if (!defined('OPENSSL_RAW_DATA')) {
+ $this->openssl_options = true;
+ } else {
+ $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
+ }
+
+ $methods = openssl_get_cipher_methods();
+ if (in_array($this->cipher_name_openssl, $methods)) {
+ return true;
+ }
+ // not all of openssl's symmetric cipher's support ctr. for those
+ // that don't we'll emulate it
+ switch ($this->mode) {
+ case self::MODE_CTR:
+ if (in_array($this->cipher_name_openssl_ecb, $methods)) {
+ $this->openssl_emulate_ctr = true;
+ return true;
+ }
+ }
+ return false;
+ case self::ENGINE_MCRYPT:
+ return $this->cipher_name_mcrypt &&
+ extension_loaded('mcrypt') &&
+ in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
+ case self::ENGINE_INTERNAL:
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Sets the preferred crypt engine
+ *
+ * Currently, $engine could be:
+ *
+ * - \phpseclib\Crypt\Base::ENGINE_OPENSSL [very fast]
+ *
+ * - \phpseclib\Crypt\Base::ENGINE_MCRYPT [fast]
+ *
+ * - \phpseclib\Crypt\Base::ENGINE_INTERNAL [slow]
+ *
+ * If the preferred crypt engine is not available the fastest available one will be used
+ *
+ * @see self::__construct()
+ * @param int $engine
+ * @access public
+ */
+ function setPreferredEngine($engine)
+ {
+ switch ($engine) {
+ //case self::ENGINE_OPENSSL;
+ case self::ENGINE_MCRYPT:
+ case self::ENGINE_INTERNAL:
+ $this->preferredEngine = $engine;
+ break;
+ default:
+ $this->preferredEngine = self::ENGINE_OPENSSL;
+ }
+
+ $this->_setEngine();
+ }
+
+ /**
+ * Returns the engine currently being utilized
+ *
+ * @see self::_setEngine()
+ * @access public
+ */
+ function getEngine()
+ {
+ return $this->engine;
+ }
+
+ /**
+ * Sets the engine as appropriate
+ *
+ * @see self::__construct()
+ * @access private
+ */
+ function _setEngine()
+ {
+ $this->engine = null;
+
+ $candidateEngines = array(
+ $this->preferredEngine,
+ self::ENGINE_OPENSSL,
+ self::ENGINE_MCRYPT
+ );
+ foreach ($candidateEngines as $engine) {
+ if ($this->isValidEngine($engine)) {
+ $this->engine = $engine;
+ break;
+ }
+ }
+ if (!$this->engine) {
+ $this->engine = self::ENGINE_INTERNAL;
+ }
+
+ if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
+ // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
+ // (re)open them with the module named in $this->cipher_name_mcrypt
+ @mcrypt_module_close($this->enmcrypt);
+ @mcrypt_module_close($this->demcrypt);
+ $this->enmcrypt = null;
+ $this->demcrypt = null;
+
+ if ($this->ecb) {
+ @mcrypt_module_close($this->ecb);
+ $this->ecb = null;
+ }
+ }
+
+ $this->changed = true;
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * Note: Must be extended by the child \phpseclib\Crypt\* class
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ abstract function _encryptBlock($in);
+
+ /**
+ * Decrypts a block
+ *
+ * Note: Must be extended by the child \phpseclib\Crypt\* class
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ abstract function _decryptBlock($in);
+
+ /**
+ * Setup the key (expansion)
+ *
+ * Only used if $engine == self::ENGINE_INTERNAL
+ *
+ * Note: Must extend by the child \phpseclib\Crypt\* class
+ *
+ * @see self::_setup()
+ * @access private
+ */
+ abstract function _setupKey();
+
+ /**
+ * Setup the self::ENGINE_INTERNAL $engine
+ *
+ * (re)init, if necessary, the internal cipher $engine and flush all $buffers
+ * Used (only) if $engine == self::ENGINE_INTERNAL
+ *
+ * _setup() will be called each time if $changed === true
+ * typically this happens when using one or more of following public methods:
+ *
+ * - setKey()
+ *
+ * - setIV()
+ *
+ * - disableContinuousBuffer()
+ *
+ * - First run of encrypt() / decrypt() with no init-settings
+ *
+ * @see self::setKey()
+ * @see self::setIV()
+ * @see self::disableContinuousBuffer()
+ * @access private
+ * @internal _setup() is always called before en/decryption.
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function _setup()
+ {
+ $this->_clearBuffers();
+ $this->_setupKey();
+
+ if ($this->use_inline_crypt) {
+ $this->_setupInlineCrypt();
+ }
+ }
+
+ /**
+ * Setup the self::ENGINE_MCRYPT $engine
+ *
+ * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
+ * Used (only) if $engine = self::ENGINE_MCRYPT
+ *
+ * _setupMcrypt() will be called each time if $changed === true
+ * typically this happens when using one or more of following public methods:
+ *
+ * - setKey()
+ *
+ * - setIV()
+ *
+ * - disableContinuousBuffer()
+ *
+ * - First run of encrypt() / decrypt()
+ *
+ * @see self::setKey()
+ * @see self::setIV()
+ * @see self::disableContinuousBuffer()
+ * @access private
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function _setupMcrypt()
+ {
+ $this->_clearBuffers();
+ $this->enchanged = $this->dechanged = true;
+
+ if (!isset($this->enmcrypt)) {
+ static $mcrypt_modes = array(
+ self::MODE_CTR => 'ctr',
+ self::MODE_ECB => MCRYPT_MODE_ECB,
+ self::MODE_CBC => MCRYPT_MODE_CBC,
+ self::MODE_CFB => 'ncfb',
+ self::MODE_CFB8 => MCRYPT_MODE_CFB,
+ self::MODE_OFB => MCRYPT_MODE_NOFB,
+ self::MODE_STREAM => MCRYPT_MODE_STREAM,
+ );
+
+ $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
+ $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
+
+ // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
+ // to workaround mcrypt's broken ncfb implementation in buffered mode
+ // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
+ if ($this->mode == self::MODE_CFB) {
+ $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
+ }
+ } // else should mcrypt_generic_deinit be called?
+
+ if ($this->mode == self::MODE_CFB) {
+ @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
+ }
+ }
+
+ /**
+ * Pads a string
+ *
+ * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
+ * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
+ * chr($this->block_size - (strlen($text) % $this->block_size)
+ *
+ * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
+ * and padding will, hence forth, be enabled.
+ *
+ * @see self::_unpad()
+ * @param string $text
+ * @access private
+ * @return string
+ */
+ function _pad($text)
+ {
+ $length = strlen($text);
+
+ if (!$this->padding) {
+ if ($length % $this->block_size == 0) {
+ return $text;
+ } else {
+ user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
+ $this->padding = true;
+ }
+ }
+
+ $pad = $this->block_size - ($length % $this->block_size);
+
+ return str_pad($text, $length + $pad, chr($pad));
+ }
+
+ /**
+ * Unpads a string.
+ *
+ * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
+ * and false will be returned.
+ *
+ * @see self::_pad()
+ * @param string $text
+ * @access private
+ * @return string
+ */
+ function _unpad($text)
+ {
+ if (!$this->padding) {
+ return $text;
+ }
+
+ $length = ord($text[strlen($text) - 1]);
+
+ if (!$length || $length > $this->block_size) {
+ return false;
+ }
+
+ return substr($text, 0, -$length);
+ }
+
+ /**
+ * Clears internal buffers
+ *
+ * Clearing/resetting the internal buffers is done everytime
+ * after disableContinuousBuffer() or on cipher $engine (re)init
+ * ie after setKey() or setIV()
+ *
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ function _clearBuffers()
+ {
+ $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
+
+ // mcrypt's handling of invalid's $iv:
+ // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
+ $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
+
+ if (!$this->skip_key_adjustment) {
+ $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
+ }
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @access private
+ * @return string
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+
+ /**
+ * String Pop
+ *
+ * Inspired by array_pop
+ *
+ * @param string $string
+ * @param int $index
+ * @access private
+ * @return string
+ */
+ function _string_pop(&$string, $index = 1)
+ {
+ $substr = substr($string, -$index);
+ $string = substr($string, 0, -$index);
+ return $substr;
+ }
+
+ /**
+ * Increment the current string
+ *
+ * @see self::decrypt()
+ * @see self::encrypt()
+ * @param string $var
+ * @access private
+ */
+ function _increment_str(&$var)
+ {
+ for ($i = 4; $i <= strlen($var); $i+= 4) {
+ $temp = substr($var, -$i, 4);
+ switch ($temp) {
+ case "\xFF\xFF\xFF\xFF":
+ $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
+ break;
+ case "\x7F\xFF\xFF\xFF":
+ $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
+ return;
+ default:
+ $temp = unpack('Nnum', $temp);
+ $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
+ return;
+ }
+ }
+
+ $remainder = strlen($var) % 4;
+
+ if ($remainder == 0) {
+ return;
+ }
+
+ $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
+ $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
+ $var = substr_replace($var, $temp, 0, $remainder);
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * Stores the created (or existing) callback function-name
+ * in $this->inline_crypt
+ *
+ * Internally for phpseclib developers:
+ *
+ * _setupInlineCrypt() would be called only if:
+ *
+ * - $engine == self::ENGINE_INTERNAL and
+ *
+ * - $use_inline_crypt === true
+ *
+ * - each time on _setup(), after(!) _setupKey()
+ *
+ *
+ * This ensures that _setupInlineCrypt() has always a
+ * full ready2go initializated internal cipher $engine state
+ * where, for example, the keys allready expanded,
+ * keys/block_size calculated and such.
+ *
+ * It is, each time if called, the responsibility of _setupInlineCrypt():
+ *
+ * - to set $this->inline_crypt to a valid and fully working callback function
+ * as a (faster) replacement for encrypt() / decrypt()
+ *
+ * - NOT to create unlimited callback functions (for memory reasons!)
+ * no matter how often _setupInlineCrypt() would be called. At some
+ * point of amount they must be generic re-useable.
+ *
+ * - the code of _setupInlineCrypt() it self,
+ * and the generated callback code,
+ * must be, in following order:
+ * - 100% safe
+ * - 100% compatible to encrypt()/decrypt()
+ * - using only php5+ features/lang-constructs/php-extensions if
+ * compatibility (down to php4) or fallback is provided
+ * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
+ * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
+ * the reason for the existence of _setupInlineCrypt() :-)]
+ * - memory-nice
+ * - short (as good as possible)
+ *
+ * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
+ * - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib\Crypt\* class.
+ * - The following variable names are reserved:
+ * - $_* (all variable names prefixed with an underscore)
+ * - $self (object reference to it self. Do not use $this, but $self instead)
+ * - $in (the content of $in has to en/decrypt by the generated code)
+ * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
+ *
+ *
+ * @see self::_setup()
+ * @see self::_createInlineCryptFunction()
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @access private
+ * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
+ */
+ function _setupInlineCrypt()
+ {
+ // If, for any reason, an extending \phpseclib\Crypt\Base() \phpseclib\Crypt\* class
+ // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
+ // ie in the class var declaration of $use_inline_crypt in general for the \phpseclib\Crypt\* class,
+ // in the constructor at object instance-time
+ // or, if it's runtime-specific, at runtime
+
+ $this->use_inline_crypt = false;
+ }
+
+ /**
+ * Creates the performance-optimized function for en/decrypt()
+ *
+ * Internally for phpseclib developers:
+ *
+ * _createInlineCryptFunction():
+ *
+ * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
+ * with the current [$this->]mode of operation code
+ *
+ * - create the $inline function, which called by encrypt() / decrypt()
+ * as its replacement to speed up the en/decryption operations.
+ *
+ * - return the name of the created $inline callback function
+ *
+ * - used to speed up en/decryption
+ *
+ *
+ *
+ * The main reason why can speed up things [up to 50%] this way are:
+ *
+ * - using variables more effective then regular.
+ * (ie no use of expensive arrays but integers $k_0, $k_1 ...
+ * or even, for example, the pure $key[] values hardcoded)
+ *
+ * - avoiding 1000's of function calls of ie _encryptBlock()
+ * but inlining the crypt operations.
+ * in the mode of operation for() loop.
+ *
+ * - full loop unroll the (sometimes key-dependent) rounds
+ * avoiding this way ++$i counters and runtime-if's etc...
+ *
+ * The basic code architectur of the generated $inline en/decrypt()
+ * lambda function, in pseudo php, is:
+ *
+ * <code>
+ * +----------------------------------------------------------------------------------------------+
+ * | callback $inline = create_function: |
+ * | lambda_function_0001_crypt_ECB($action, $text) |
+ * | { |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['init_crypt']; // general init code. |
+ * | // ie: $sbox'es declarations used for |
+ * | // encrypt and decrypt'ing. |
+ * | |
+ * | switch ($action) { |
+ * | case 'encrypt': |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
+ * | ie: specified $key or $box |
+ * | declarations for encrypt'ing. |
+ * | |
+ * | foreach ($ciphertext) { |
+ * | $in = $block_size of $ciphertext; |
+ * | |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
+ * | // strlen($in) == $this->block_size |
+ * | // here comes the cipher algorithm in action |
+ * | // for encryption. |
+ * | // $cipher_code['encrypt_block'] has to |
+ * | // encrypt the content of the $in variable |
+ * | |
+ * | $plaintext .= $in; |
+ * | } |
+ * | return $plaintext; |
+ * | |
+ * | case 'decrypt': |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
+ * | ie: specified $key or $box |
+ * | declarations for decrypt'ing. |
+ * | foreach ($plaintext) { |
+ * | $in = $block_size of $plaintext; |
+ * | |
+ * | INSERT PHP CODE OF: |
+ * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
+ * | // strlen($in) == $this->block_size |
+ * | // here comes the cipher algorithm in action |
+ * | // for decryption. |
+ * | // $cipher_code['decrypt_block'] has to |
+ * | // decrypt the content of the $in variable |
+ * | $ciphertext .= $in; |
+ * | } |
+ * | return $ciphertext; |
+ * | } |
+ * | } |
+ * +----------------------------------------------------------------------------------------------+
+ * </code>
+ *
+ * See also the \phpseclib\Crypt\*::_setupInlineCrypt()'s for
+ * productive inline $cipher_code's how they works.
+ *
+ * Structure of:
+ * <code>
+ * $cipher_code = array(
+ * 'init_crypt' => (string) '', // optional
+ * 'init_encrypt' => (string) '', // optional
+ * 'init_decrypt' => (string) '', // optional
+ * 'encrypt_block' => (string) '', // required
+ * 'decrypt_block' => (string) '' // required
+ * );
+ * </code>
+ *
+ * @see self::_setupInlineCrypt()
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @param array $cipher_code
+ * @access private
+ * @return string (the name of the created callback function)
+ */
+ function _createInlineCryptFunction($cipher_code)
+ {
+ $block_size = $this->block_size;
+
+ // optional
+ $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
+ $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
+ $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
+ // required
+ $encrypt_block = $cipher_code['encrypt_block'];
+ $decrypt_block = $cipher_code['decrypt_block'];
+
+ // Generating mode of operation inline code,
+ // merged with the $cipher_code algorithm
+ // for encrypt- and decryption.
+ switch ($this->mode) {
+ case self::MODE_ECB:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_plaintext_len = strlen($_text);
+
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $in = substr($_text, $_i, '.$block_size.');
+ '.$encrypt_block.'
+ $_ciphertext.= $in;
+ }
+
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_decrypt . '
+ $_plaintext = "";
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
+ $_ciphertext_len = strlen($_text);
+
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $in = substr($_text, $_i, '.$block_size.');
+ '.$decrypt_block.'
+ $_plaintext.= $in;
+ }
+
+ return $self->_unpad($_plaintext);
+ ';
+ break;
+ case self::MODE_CTR:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_plaintext_len = strlen($_text);
+ $_xor = $self->encryptIV;
+ $_buffer = &$self->enbuffer;
+ if (strlen($_buffer["ciphertext"])) {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $self->_increment_str($_xor);
+ $_buffer["ciphertext"].= $in;
+ }
+ $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
+ $_ciphertext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ $in = $_xor;
+ '.$encrypt_block.'
+ $self->_increment_str($_xor);
+ $_key = $in;
+ $_ciphertext.= $_block ^ $_key;
+ }
+ }
+ if ($self->continuousBuffer) {
+ $self->encryptIV = $_xor;
+ if ($_start = $_plaintext_len % '.$block_size.') {
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
+ }
+ }
+
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_ciphertext_len = strlen($_text);
+ $_xor = $self->decryptIV;
+ $_buffer = &$self->debuffer;
+
+ if (strlen($_buffer["ciphertext"])) {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $self->_increment_str($_xor);
+ $_buffer["ciphertext"].= $in;
+ }
+ $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
+ $_plaintext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ $in = $_xor;
+ '.$encrypt_block.'
+ $self->_increment_str($_xor);
+ $_key = $in;
+ $_plaintext.= $_block ^ $_key;
+ }
+ }
+ if ($self->continuousBuffer) {
+ $self->decryptIV = $_xor;
+ if ($_start = $_ciphertext_len % '.$block_size.') {
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
+ }
+ }
+
+ return $_plaintext;
+ ';
+ break;
+ case self::MODE_CFB:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_buffer = &$self->enbuffer;
+
+ if ($self->continuousBuffer) {
+ $_iv = &$self->encryptIV;
+ $_pos = &$_buffer["pos"];
+ } else {
+ $_iv = $self->encryptIV;
+ $_pos = 0;
+ }
+ $_len = strlen($_text);
+ $_i = 0;
+ if ($_pos) {
+ $_orig_pos = $_pos;
+ $_max = '.$block_size.' - $_pos;
+ if ($_len >= $_max) {
+ $_i = $_max;
+ $_len-= $_max;
+ $_pos = 0;
+ } else {
+ $_i = $_len;
+ $_pos+= $_len;
+ $_len = 0;
+ }
+ $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
+ $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
+ }
+ while ($_len >= '.$block_size.') {
+ $in = $_iv;
+ '.$encrypt_block.';
+ $_iv = $in ^ substr($_text, $_i, '.$block_size.');
+ $_ciphertext.= $_iv;
+ $_len-= '.$block_size.';
+ $_i+= '.$block_size.';
+ }
+ if ($_len) {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_iv = $in;
+ $_block = $_iv ^ substr($_text, $_i);
+ $_iv = substr_replace($_iv, $_block, 0, $_len);
+ $_ciphertext.= $_block;
+ $_pos = $_len;
+ }
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_buffer = &$self->debuffer;
+
+ if ($self->continuousBuffer) {
+ $_iv = &$self->decryptIV;
+ $_pos = &$_buffer["pos"];
+ } else {
+ $_iv = $self->decryptIV;
+ $_pos = 0;
+ }
+ $_len = strlen($_text);
+ $_i = 0;
+ if ($_pos) {
+ $_orig_pos = $_pos;
+ $_max = '.$block_size.' - $_pos;
+ if ($_len >= $_max) {
+ $_i = $_max;
+ $_len-= $_max;
+ $_pos = 0;
+ } else {
+ $_i = $_len;
+ $_pos+= $_len;
+ $_len = 0;
+ }
+ $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
+ $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
+ }
+ while ($_len >= '.$block_size.') {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_iv = $in;
+ $cb = substr($_text, $_i, '.$block_size.');
+ $_plaintext.= $_iv ^ $cb;
+ $_iv = $cb;
+ $_len-= '.$block_size.';
+ $_i+= '.$block_size.';
+ }
+ if ($_len) {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_iv = $in;
+ $_plaintext.= $_iv ^ substr($_text, $_i);
+ $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
+ $_pos = $_len;
+ }
+
+ return $_plaintext;
+ ';
+ break;
+ case self::MODE_CFB8:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_len = strlen($_text);
+ $_iv = $self->encryptIV;
+
+ for ($_i = 0; $_i < $_len; ++$_i) {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_ciphertext .= ($_c = $_text[$_i] ^ $in);
+ $_iv = substr($_iv, 1) . $_c;
+ }
+
+ if ($self->continuousBuffer) {
+ if ($_len >= '.$block_size.') {
+ $self->encryptIV = substr($_ciphertext, -'.$block_size.');
+ } else {
+ $self->encryptIV = substr($self->encryptIV, $_len - '.$block_size.') . substr($_ciphertext, -$_len);
+ }
+ }
+
+ return $_ciphertext;
+ ';
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_len = strlen($_text);
+ $_iv = $self->decryptIV;
+
+ for ($_i = 0; $_i < $_len; ++$_i) {
+ $in = $_iv;
+ '.$encrypt_block.'
+ $_plaintext .= $_text[$_i] ^ $in;
+ $_iv = substr($_iv, 1) . $_text[$_i];
+ }
+
+ if ($self->continuousBuffer) {
+ if ($_len >= '.$block_size.') {
+ $self->decryptIV = substr($_text, -'.$block_size.');
+ } else {
+ $self->decryptIV = substr($self->decryptIV, $_len - '.$block_size.') . substr($_text, -$_len);
+ }
+ }
+
+ return $_plaintext;
+ ';
+ break;
+ case self::MODE_OFB:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_plaintext_len = strlen($_text);
+ $_xor = $self->encryptIV;
+ $_buffer = &$self->enbuffer;
+
+ if (strlen($_buffer["xor"])) {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["xor"])) {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_buffer["xor"].= $_xor;
+ }
+ $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
+ $_ciphertext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
+ }
+ $_key = $_xor;
+ }
+ if ($self->continuousBuffer) {
+ $self->encryptIV = $_xor;
+ if ($_start = $_plaintext_len % '.$block_size.') {
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
+ }
+ }
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_encrypt . '
+ $_plaintext = "";
+ $_ciphertext_len = strlen($_text);
+ $_xor = $self->decryptIV;
+ $_buffer = &$self->debuffer;
+
+ if (strlen($_buffer["xor"])) {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $_block = substr($_text, $_i, '.$block_size.');
+ if (strlen($_block) > strlen($_buffer["xor"])) {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_buffer["xor"].= $_xor;
+ }
+ $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
+ $_plaintext.= $_block ^ $_key;
+ }
+ } else {
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $in = $_xor;
+ '.$encrypt_block.'
+ $_xor = $in;
+ $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
+ }
+ $_key = $_xor;
+ }
+ if ($self->continuousBuffer) {
+ $self->decryptIV = $_xor;
+ if ($_start = $_ciphertext_len % '.$block_size.') {
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
+ }
+ }
+ return $_plaintext;
+ ';
+ break;
+ case self::MODE_STREAM:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ '.$encrypt_block.'
+ return $_ciphertext;
+ ';
+ $decrypt = $init_decrypt . '
+ $_plaintext = "";
+ '.$decrypt_block.'
+ return $_plaintext;
+ ';
+ break;
+ // case self::MODE_CBC:
+ default:
+ $encrypt = $init_encrypt . '
+ $_ciphertext = "";
+ $_plaintext_len = strlen($_text);
+
+ $in = $self->encryptIV;
+
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
+ $in = substr($_text, $_i, '.$block_size.') ^ $in;
+ '.$encrypt_block.'
+ $_ciphertext.= $in;
+ }
+
+ if ($self->continuousBuffer) {
+ $self->encryptIV = $in;
+ }
+
+ return $_ciphertext;
+ ';
+
+ $decrypt = $init_decrypt . '
+ $_plaintext = "";
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
+ $_ciphertext_len = strlen($_text);
+
+ $_iv = $self->decryptIV;
+
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
+ $in = $_block = substr($_text, $_i, '.$block_size.');
+ '.$decrypt_block.'
+ $_plaintext.= $in ^ $_iv;
+ $_iv = $_block;
+ }
+
+ if ($self->continuousBuffer) {
+ $self->decryptIV = $_iv;
+ }
+
+ return $self->_unpad($_plaintext);
+ ';
+ break;
+ }
+
+ // Create the $inline function and return its name as string. Ready to run!
+ if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
+ eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
+ return $func;
+ }
+
+ return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
+ }
+
+ /**
+ * Holds the lambda_functions table (classwide)
+ *
+ * Each name of the lambda function, created from
+ * _setupInlineCrypt() && _createInlineCryptFunction()
+ * is stored, classwide (!), here for reusing.
+ *
+ * The string-based index of $function is a classwide
+ * unique value representing, at least, the $mode of
+ * operation (or more... depends of the optimizing level)
+ * for which $mode the lambda function was created.
+ *
+ * @access private
+ * @return array &$functions
+ */
+ function &_getLambdaFunctions()
+ {
+ static $functions = array();
+ return $functions;
+ }
+
+ /**
+ * Generates a digest from $bytes
+ *
+ * @see self::_setupInlineCrypt()
+ * @access private
+ * @param $bytes
+ * @return string
+ */
+ function _hashInlineCryptFunction($bytes)
+ {
+ if (!isset(self::$WHIRLPOOL_AVAILABLE)) {
+ self::$WHIRLPOOL_AVAILABLE = extension_loaded('hash') && in_array('whirlpool', hash_algos());
+ }
+
+ $result = '';
+ $hash = $bytes;
+
+ switch (true) {
+ case self::$WHIRLPOOL_AVAILABLE:
+ foreach (str_split($bytes, 64) as $t) {
+ $hash = hash('whirlpool', $hash, true);
+ $result .= $t ^ $hash;
+ }
+ return $result . hash('whirlpool', $hash, true);
+ default:
+ $len = strlen($bytes);
+ for ($i = 0; $i < $len; $i+=20) {
+ $t = substr($bytes, $i, 20);
+ $hash = pack('H*', sha1($hash));
+ $result .= $t ^ $hash;
+ }
+ return $result . pack('H*', sha1($hash));
+ }
+ }
+
+ /**
+ * Convert float to int
+ *
+ * On ARM CPUs converting floats to ints doesn't always work
+ *
+ * @access private
+ * @param string $x
+ * @return int
+ */
+ function safe_intval($x)
+ {
+ switch (true) {
+ case is_int($x):
+ // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
+ case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
+ return $x;
+ }
+ return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
+ ((fmod(floor($x / 0x80000000), 2) & 1) << 31);
+ }
+
+ /**
+ * eval()'able string for in-line float to int
+ *
+ * @access private
+ * @return string
+ */
+ function safe_intval_inline()
+ {
+ switch (true) {
+ case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
+ case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
+ return '%s';
+ break;
+ default:
+ $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
+ return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of Blowfish.
+ *
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $blowfish = new \phpseclib\Crypt\Blowfish();
+ *
+ * $blowfish->setKey('12345678901234567890123456789012');
+ *
+ * $plaintext = str_repeat('a', 1024);
+ *
+ * echo $blowfish->decrypt($blowfish->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package Blowfish
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of Blowfish.
+ *
+ * @package Blowfish
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @access public
+ */
+class Blowfish extends Base
+{
+ /**
+ * Block Length of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::block_size
+ * @var int
+ * @access private
+ */
+ var $block_size = 8;
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'blowfish';
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * @see \phpseclib\Crypt\Base::cfb_init_len
+ * @var int
+ * @access private
+ */
+ var $cfb_init_len = 500;
+
+ /**
+ * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
+ *
+ * S-Box 0
+ *
+ * @access private
+ * @var array
+ */
+ var $sbox0 = array(
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+ );
+
+ /**
+ * S-Box 1
+ *
+ * @access private
+ * @var array
+ */
+ var $sbox1 = array(
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+ );
+
+ /**
+ * S-Box 2
+ *
+ * @access private
+ * @var array
+ */
+ var $sbox2 = array(
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+ );
+
+ /**
+ * S-Box 3
+ *
+ * @access private
+ * @var array
+ */
+ var $sbox3 = array(
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+ );
+
+ /**
+ * P-Array consists of 18 32-bit subkeys
+ *
+ * @var array
+ * @access private
+ */
+ var $parray = array(
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
+ );
+
+ /**
+ * The BCTX-working Array
+ *
+ * Holds the expanded key [p] and the key-depended s-boxes [sb]
+ *
+ * @var array
+ * @access private
+ */
+ var $bctx;
+
+ /**
+ * Holds the last used key
+ *
+ * @var array
+ * @access private
+ */
+ var $kl;
+
+ /**
+ * The Key Length (in bytes)
+ *
+ * @see \phpseclib\Crypt\Base::setKeyLength()
+ * @var int
+ * @access private
+ * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
+ * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
+ * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
+ * of that, we'll just precompute it once.
+ */
+ var $key_length = 16;
+
+ /**
+ * Sets the key length.
+ *
+ * Key lengths can be between 32 and 448 bits.
+ *
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ if ($length < 32) {
+ $this->key_length = 4;
+ } elseif ($length > 448) {
+ $this->key_length = 56;
+ } else {
+ $this->key_length = $length >> 3;
+ }
+
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Test for engine validity
+ *
+ * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
+ *
+ * @see \phpseclib\Crypt\Base::isValidEngine()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ if ($engine == self::ENGINE_OPENSSL) {
+ if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) {
+ return false;
+ }
+ if ($this->key_length < 16) {
+ return false;
+ }
+ $this->cipher_name_openssl_ecb = 'bf-ecb';
+ $this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
+ }
+
+ return parent::isValidEngine($engine);
+ }
+
+ /**
+ * Setup the key (expansion)
+ *
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
+ // already expanded
+ return;
+ }
+ $this->kl = array('key' => $this->key);
+
+ /* key-expanding p[] and S-Box building sb[] */
+ $this->bctx = array(
+ 'p' => array(),
+ 'sb' => array(
+ $this->sbox0,
+ $this->sbox1,
+ $this->sbox2,
+ $this->sbox3
+ )
+ );
+
+ // unpack binary string in unsigned chars
+ $key = array_values(unpack('C*', $this->key));
+ $keyl = count($key);
+ for ($j = 0, $i = 0; $i < 18; ++$i) {
+ // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
+ for ($data = 0, $k = 0; $k < 4; ++$k) {
+ $data = ($data << 8) | $key[$j];
+ if (++$j >= $keyl) {
+ $j = 0;
+ }
+ }
+ $this->bctx['p'][] = $this->parray[$i] ^ $data;
+ }
+
+ // encrypt the zero-string, replace P1 and P2 with the encrypted data,
+ // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
+ $data = "\0\0\0\0\0\0\0\0";
+ for ($i = 0; $i < 18; $i += 2) {
+ list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
+ $this->bctx['p'][$i ] = $l;
+ $this->bctx['p'][$i + 1] = $r;
+ }
+ for ($i = 0; $i < 4; ++$i) {
+ for ($j = 0; $j < 256; $j += 2) {
+ list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
+ $this->bctx['sb'][$i][$j ] = $l;
+ $this->bctx['sb'][$i][$j + 1] = $r;
+ }
+ }
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _encryptBlock($in)
+ {
+ $p = $this->bctx["p"];
+ // extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
+ $sb_0 = $this->bctx["sb"][0];
+ $sb_1 = $this->bctx["sb"][1];
+ $sb_2 = $this->bctx["sb"][2];
+ $sb_3 = $this->bctx["sb"][3];
+
+ $in = unpack("N*", $in);
+ $l = $in[1];
+ $r = $in[2];
+
+ for ($i = 0; $i < 16; $i+= 2) {
+ $l^= $p[$i];
+ $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
+ $sb_2[$l >> 8 & 0xff]) +
+ $sb_3[$l & 0xff]);
+
+ $r^= $p[$i + 1];
+ $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
+ $sb_2[$r >> 8 & 0xff]) +
+ $sb_3[$r & 0xff]);
+ }
+ return pack("N*", $r ^ $p[17], $l ^ $p[16]);
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _decryptBlock($in)
+ {
+ $p = $this->bctx["p"];
+ $sb_0 = $this->bctx["sb"][0];
+ $sb_1 = $this->bctx["sb"][1];
+ $sb_2 = $this->bctx["sb"][2];
+ $sb_3 = $this->bctx["sb"][3];
+
+ $in = unpack("N*", $in);
+ $l = $in[1];
+ $r = $in[2];
+
+ for ($i = 17; $i > 2; $i-= 2) {
+ $l^= $p[$i];
+ $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
+ $sb_2[$l >> 8 & 0xff]) +
+ $sb_3[$l & 0xff]);
+
+ $r^= $p[$i - 1];
+ $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
+ $sb_2[$r >> 8 & 0xff]) +
+ $sb_3[$r & 0xff]);
+ }
+ return pack("N*", $r ^ $p[0], $l ^ $p[1]);
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ $lambda_functions =& self::_getLambdaFunctions();
+
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
+ // (Currently, for Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
+
+ // Generation of a unique hash for our generated code
+ $code_hash = "Crypt_Blowfish, {$this->mode}";
+ if ($gen_hi_opt_code) {
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
+ }
+
+ $safeint = $this->safe_intval_inline();
+
+ if (!isset($lambda_functions[$code_hash])) {
+ switch (true) {
+ case $gen_hi_opt_code:
+ $p = $this->bctx['p'];
+ $init_crypt = '
+ static $sb_0, $sb_1, $sb_2, $sb_3;
+ if (!$sb_0) {
+ $sb_0 = $self->bctx["sb"][0];
+ $sb_1 = $self->bctx["sb"][1];
+ $sb_2 = $self->bctx["sb"][2];
+ $sb_3 = $self->bctx["sb"][3];
+ }
+ ';
+ break;
+ default:
+ $p = array();
+ for ($i = 0; $i < 18; ++$i) {
+ $p[] = '$p_' . $i;
+ }
+ $init_crypt = '
+ list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
+ list(' . implode(',', $p) . ') = $self->bctx["p"];
+
+ ';
+ }
+
+ // Generating encrypt code:
+ $encrypt_block = '
+ $in = unpack("N*", $in);
+ $l = $in[1];
+ $r = $in[2];
+ ';
+ for ($i = 0; $i < 16; $i+= 2) {
+ $encrypt_block.= '
+ $l^= ' . $p[$i] . ';
+ $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
+ $sb_2[$l >> 8 & 0xff]) +
+ $sb_3[$l & 0xff]') . ';
+
+ $r^= ' . $p[$i + 1] . ';
+ $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
+ $sb_2[$r >> 8 & 0xff]) +
+ $sb_3[$r & 0xff]') . ';
+ ';
+ }
+ $encrypt_block.= '
+ $in = pack("N*",
+ $r ^ ' . $p[17] . ',
+ $l ^ ' . $p[16] . '
+ );
+ ';
+
+ // Generating decrypt code:
+ $decrypt_block = '
+ $in = unpack("N*", $in);
+ $l = $in[1];
+ $r = $in[2];
+ ';
+
+ for ($i = 17; $i > 2; $i-= 2) {
+ $decrypt_block.= '
+ $l^= ' . $p[$i] . ';
+ $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
+ $sb_2[$l >> 8 & 0xff]) +
+ $sb_3[$l & 0xff]') . ';
+
+ $r^= ' . $p[$i - 1] . ';
+ $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
+ $sb_2[$r >> 8 & 0xff]) +
+ $sb_3[$r & 0xff]') . ';
+ ';
+ }
+
+ $decrypt_block.= '
+ $in = pack("N*",
+ $r ^ ' . $p[0] . ',
+ $l ^ ' . $p[1] . '
+ );
+ ';
+
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
+ array(
+ 'init_crypt' => $init_crypt,
+ 'init_encrypt' => '',
+ 'init_decrypt' => '',
+ 'encrypt_block' => $encrypt_block,
+ 'decrypt_block' => $decrypt_block
+ )
+ );
+ }
+ $this->inline_crypt = $lambda_functions[$code_hash];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of DES.
+ *
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
+ * - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
+ * - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $des = new \phpseclib\Crypt\DES();
+ *
+ * $des->setKey('abcdefgh');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $des->decrypt($des->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package DES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of DES.
+ *
+ * @package DES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class DES extends Base
+{
+ /**#@+
+ * @access private
+ * @see \phpseclib\Crypt\DES::_setupKey()
+ * @see \phpseclib\Crypt\DES::_processBlock()
+ */
+ /**
+ * Contains $keys[self::ENCRYPT]
+ */
+ const ENCRYPT = 0;
+ /**
+ * Contains $keys[self::DECRYPT]
+ */
+ const DECRYPT = 1;
+ /**#@-*/
+
+ /**
+ * Block Length of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::block_size
+ * @var int
+ * @access private
+ */
+ var $block_size = 8;
+
+ /**
+ * Key Length (in bytes)
+ *
+ * @see \phpseclib\Crypt\Base::setKeyLength()
+ * @var int
+ * @access private
+ */
+ var $key_length = 8;
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'des';
+
+ /**
+ * The OpenSSL names of the cipher / modes
+ *
+ * @see \phpseclib\Crypt\Base::openssl_mode_names
+ * @var array
+ * @access private
+ */
+ var $openssl_mode_names = array(
+ self::MODE_ECB => 'des-ecb',
+ self::MODE_CBC => 'des-cbc',
+ self::MODE_CFB => 'des-cfb',
+ self::MODE_OFB => 'des-ofb'
+ // self::MODE_CTR is undefined for DES
+ );
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * @see \phpseclib\Crypt\Base::cfb_init_len
+ * @var int
+ * @access private
+ */
+ var $cfb_init_len = 500;
+
+ /**
+ * Switch for DES/3DES encryption
+ *
+ * Used only if $engine == self::ENGINE_INTERNAL
+ *
+ * @see self::_setupKey()
+ * @see self::_processBlock()
+ * @var int
+ * @access private
+ */
+ var $des_rounds = 1;
+
+ /**
+ * max possible size of $key
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $key_length_max = 8;
+
+ /**
+ * The Key Schedule
+ *
+ * @see self::_setupKey()
+ * @var array
+ * @access private
+ */
+ var $keys;
+
+ /**
+ * Shuffle table.
+ *
+ * For each byte value index, the entry holds an 8-byte string
+ * with each byte containing all bits in the same state as the
+ * corresponding bit in the index value.
+ *
+ * @see self::_processBlock()
+ * @see self::_setupKey()
+ * @var array
+ * @access private
+ */
+ var $shuffle = array(
+ "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF",
+ "\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF",
+ "\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF",
+ "\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF",
+ "\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF",
+ "\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF",
+ "\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF",
+ "\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+ "\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF",
+ "\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF",
+ "\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF",
+ "\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF",
+ "\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF",
+ "\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF",
+ "\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF",
+ "\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF",
+ "\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF",
+ "\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF",
+ "\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF",
+ "\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF",
+ "\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF",
+ "\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF",
+ "\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF",
+ "\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF",
+ "\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF",
+ "\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF",
+ "\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF",
+ "\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF",
+ "\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF",
+ "\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF",
+ "\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF",
+ "\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
+ "\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF",
+ "\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF",
+ "\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF",
+ "\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF",
+ "\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF",
+ "\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF",
+ "\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF",
+ "\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF",
+ "\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF",
+ "\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF",
+ "\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF",
+ "\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF",
+ "\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF",
+ "\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF",
+ "\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF",
+ "\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF",
+ "\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF",
+ "\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF",
+ "\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF",
+ "\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF",
+ "\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF",
+ "\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF",
+ "\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF",
+ "\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF",
+ "\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF",
+ "\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF",
+ "\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF",
+ "\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF",
+ "\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF",
+ "\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF",
+ "\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF",
+ "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ "\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF",
+ "\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF",
+ "\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF",
+ "\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF",
+ "\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF",
+ "\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF",
+ "\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF",
+ "\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF",
+ "\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF",
+ "\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF",
+ "\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF",
+ "\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF",
+ "\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF",
+ "\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF",
+ "\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF",
+ "\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF",
+ "\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF",
+ "\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF",
+ "\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF",
+ "\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF",
+ "\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF",
+ "\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF",
+ "\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF",
+ "\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF",
+ "\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF",
+ "\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF",
+ "\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF",
+ "\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF",
+ "\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF",
+ "\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF",
+ "\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF",
+ "\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF",
+ "\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF",
+ "\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF",
+ "\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF",
+ "\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF",
+ "\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF",
+ "\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF",
+ "\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF",
+ "\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF",
+ "\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF",
+ "\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF",
+ "\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF",
+ "\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF",
+ "\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF",
+ "\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF",
+ "\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF",
+ "\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF",
+ "\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF",
+ "\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF",
+ "\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF",
+ "\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF",
+ "\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF",
+ "\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF",
+ "\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF",
+ "\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF",
+ "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF",
+ "\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF",
+ "\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF",
+ "\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF",
+ "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF",
+ "\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF",
+ "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF",
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ );
+
+ /**
+ * IP mapping helper table.
+ *
+ * Indexing this table with each source byte performs the initial bit permutation.
+ *
+ * @var array
+ * @access private
+ */
+ var $ipmap = array(
+ 0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31,
+ 0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33,
+ 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71,
+ 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73,
+ 0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35,
+ 0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37,
+ 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75,
+ 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77,
+ 0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1,
+ 0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3,
+ 0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1,
+ 0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3,
+ 0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5,
+ 0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7,
+ 0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5,
+ 0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7,
+ 0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39,
+ 0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B,
+ 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79,
+ 0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D,
+ 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
+ 0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D,
+ 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
+ 0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9,
+ 0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB,
+ 0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9,
+ 0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB,
+ 0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD,
+ 0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF,
+ 0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD,
+ 0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF
+ );
+
+ /**
+ * Inverse IP mapping helper table.
+ * Indexing this table with a byte value reverses the bit order.
+ *
+ * @var array
+ * @access private
+ */
+ var $invipmap = array(
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+ 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+ 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+ 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+ 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+ 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+ 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+ 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+ 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+ 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+ 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+ );
+
+ /**
+ * Pre-permuted S-box1
+ *
+ * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
+ * P table: concatenation can then be replaced by exclusive ORs.
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox1 = array(
+ 0x00808200, 0x00000000, 0x00008000, 0x00808202,
+ 0x00808002, 0x00008202, 0x00000002, 0x00008000,
+ 0x00000200, 0x00808200, 0x00808202, 0x00000200,
+ 0x00800202, 0x00808002, 0x00800000, 0x00000002,
+ 0x00000202, 0x00800200, 0x00800200, 0x00008200,
+ 0x00008200, 0x00808000, 0x00808000, 0x00800202,
+ 0x00008002, 0x00800002, 0x00800002, 0x00008002,
+ 0x00000000, 0x00000202, 0x00008202, 0x00800000,
+ 0x00008000, 0x00808202, 0x00000002, 0x00808000,
+ 0x00808200, 0x00800000, 0x00800000, 0x00000200,
+ 0x00808002, 0x00008000, 0x00008200, 0x00800002,
+ 0x00000200, 0x00000002, 0x00800202, 0x00008202,
+ 0x00808202, 0x00008002, 0x00808000, 0x00800202,
+ 0x00800002, 0x00000202, 0x00008202, 0x00808200,
+ 0x00000202, 0x00800200, 0x00800200, 0x00000000,
+ 0x00008002, 0x00008200, 0x00000000, 0x00808002
+ );
+
+ /**
+ * Pre-permuted S-box2
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox2 = array(
+ 0x40084010, 0x40004000, 0x00004000, 0x00084010,
+ 0x00080000, 0x00000010, 0x40080010, 0x40004010,
+ 0x40000010, 0x40084010, 0x40084000, 0x40000000,
+ 0x40004000, 0x00080000, 0x00000010, 0x40080010,
+ 0x00084000, 0x00080010, 0x40004010, 0x00000000,
+ 0x40000000, 0x00004000, 0x00084010, 0x40080000,
+ 0x00080010, 0x40000010, 0x00000000, 0x00084000,
+ 0x00004010, 0x40084000, 0x40080000, 0x00004010,
+ 0x00000000, 0x00084010, 0x40080010, 0x00080000,
+ 0x40004010, 0x40080000, 0x40084000, 0x00004000,
+ 0x40080000, 0x40004000, 0x00000010, 0x40084010,
+ 0x00084010, 0x00000010, 0x00004000, 0x40000000,
+ 0x00004010, 0x40084000, 0x00080000, 0x40000010,
+ 0x00080010, 0x40004010, 0x40000010, 0x00080010,
+ 0x00084000, 0x00000000, 0x40004000, 0x00004010,
+ 0x40000000, 0x40080010, 0x40084010, 0x00084000
+ );
+
+ /**
+ * Pre-permuted S-box3
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox3 = array(
+ 0x00000104, 0x04010100, 0x00000000, 0x04010004,
+ 0x04000100, 0x00000000, 0x00010104, 0x04000100,
+ 0x00010004, 0x04000004, 0x04000004, 0x00010000,
+ 0x04010104, 0x00010004, 0x04010000, 0x00000104,
+ 0x04000000, 0x00000004, 0x04010100, 0x00000100,
+ 0x00010100, 0x04010000, 0x04010004, 0x00010104,
+ 0x04000104, 0x00010100, 0x00010000, 0x04000104,
+ 0x00000004, 0x04010104, 0x00000100, 0x04000000,
+ 0x04010100, 0x04000000, 0x00010004, 0x00000104,
+ 0x00010000, 0x04010100, 0x04000100, 0x00000000,
+ 0x00000100, 0x00010004, 0x04010104, 0x04000100,
+ 0x04000004, 0x00000100, 0x00000000, 0x04010004,
+ 0x04000104, 0x00010000, 0x04000000, 0x04010104,
+ 0x00000004, 0x00010104, 0x00010100, 0x04000004,
+ 0x04010000, 0x04000104, 0x00000104, 0x04010000,
+ 0x00010104, 0x00000004, 0x04010004, 0x00010100
+ );
+
+ /**
+ * Pre-permuted S-box4
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox4 = array(
+ 0x80401000, 0x80001040, 0x80001040, 0x00000040,
+ 0x00401040, 0x80400040, 0x80400000, 0x80001000,
+ 0x00000000, 0x00401000, 0x00401000, 0x80401040,
+ 0x80000040, 0x00000000, 0x00400040, 0x80400000,
+ 0x80000000, 0x00001000, 0x00400000, 0x80401000,
+ 0x00000040, 0x00400000, 0x80001000, 0x00001040,
+ 0x80400040, 0x80000000, 0x00001040, 0x00400040,
+ 0x00001000, 0x00401040, 0x80401040, 0x80000040,
+ 0x00400040, 0x80400000, 0x00401000, 0x80401040,
+ 0x80000040, 0x00000000, 0x00000000, 0x00401000,
+ 0x00001040, 0x00400040, 0x80400040, 0x80000000,
+ 0x80401000, 0x80001040, 0x80001040, 0x00000040,
+ 0x80401040, 0x80000040, 0x80000000, 0x00001000,
+ 0x80400000, 0x80001000, 0x00401040, 0x80400040,
+ 0x80001000, 0x00001040, 0x00400000, 0x80401000,
+ 0x00000040, 0x00400000, 0x00001000, 0x00401040
+ );
+
+ /**
+ * Pre-permuted S-box5
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox5 = array(
+ 0x00000080, 0x01040080, 0x01040000, 0x21000080,
+ 0x00040000, 0x00000080, 0x20000000, 0x01040000,
+ 0x20040080, 0x00040000, 0x01000080, 0x20040080,
+ 0x21000080, 0x21040000, 0x00040080, 0x20000000,
+ 0x01000000, 0x20040000, 0x20040000, 0x00000000,
+ 0x20000080, 0x21040080, 0x21040080, 0x01000080,
+ 0x21040000, 0x20000080, 0x00000000, 0x21000000,
+ 0x01040080, 0x01000000, 0x21000000, 0x00040080,
+ 0x00040000, 0x21000080, 0x00000080, 0x01000000,
+ 0x20000000, 0x01040000, 0x21000080, 0x20040080,
+ 0x01000080, 0x20000000, 0x21040000, 0x01040080,
+ 0x20040080, 0x00000080, 0x01000000, 0x21040000,
+ 0x21040080, 0x00040080, 0x21000000, 0x21040080,
+ 0x01040000, 0x00000000, 0x20040000, 0x21000000,
+ 0x00040080, 0x01000080, 0x20000080, 0x00040000,
+ 0x00000000, 0x20040000, 0x01040080, 0x20000080
+ );
+
+ /**
+ * Pre-permuted S-box6
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox6 = array(
+ 0x10000008, 0x10200000, 0x00002000, 0x10202008,
+ 0x10200000, 0x00000008, 0x10202008, 0x00200000,
+ 0x10002000, 0x00202008, 0x00200000, 0x10000008,
+ 0x00200008, 0x10002000, 0x10000000, 0x00002008,
+ 0x00000000, 0x00200008, 0x10002008, 0x00002000,
+ 0x00202000, 0x10002008, 0x00000008, 0x10200008,
+ 0x10200008, 0x00000000, 0x00202008, 0x10202000,
+ 0x00002008, 0x00202000, 0x10202000, 0x10000000,
+ 0x10002000, 0x00000008, 0x10200008, 0x00202000,
+ 0x10202008, 0x00200000, 0x00002008, 0x10000008,
+ 0x00200000, 0x10002000, 0x10000000, 0x00002008,
+ 0x10000008, 0x10202008, 0x00202000, 0x10200000,
+ 0x00202008, 0x10202000, 0x00000000, 0x10200008,
+ 0x00000008, 0x00002000, 0x10200000, 0x00202008,
+ 0x00002000, 0x00200008, 0x10002008, 0x00000000,
+ 0x10202000, 0x10000000, 0x00200008, 0x10002008
+ );
+
+ /**
+ * Pre-permuted S-box7
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox7 = array(
+ 0x00100000, 0x02100001, 0x02000401, 0x00000000,
+ 0x00000400, 0x02000401, 0x00100401, 0x02100400,
+ 0x02100401, 0x00100000, 0x00000000, 0x02000001,
+ 0x00000001, 0x02000000, 0x02100001, 0x00000401,
+ 0x02000400, 0x00100401, 0x00100001, 0x02000400,
+ 0x02000001, 0x02100000, 0x02100400, 0x00100001,
+ 0x02100000, 0x00000400, 0x00000401, 0x02100401,
+ 0x00100400, 0x00000001, 0x02000000, 0x00100400,
+ 0x02000000, 0x00100400, 0x00100000, 0x02000401,
+ 0x02000401, 0x02100001, 0x02100001, 0x00000001,
+ 0x00100001, 0x02000000, 0x02000400, 0x00100000,
+ 0x02100400, 0x00000401, 0x00100401, 0x02100400,
+ 0x00000401, 0x02000001, 0x02100401, 0x02100000,
+ 0x00100400, 0x00000000, 0x00000001, 0x02100401,
+ 0x00000000, 0x00100401, 0x02100000, 0x00000400,
+ 0x02000001, 0x02000400, 0x00000400, 0x00100001
+ );
+
+ /**
+ * Pre-permuted S-box8
+ *
+ * @var array
+ * @access private
+ */
+ var $sbox8 = array(
+ 0x08000820, 0x00000800, 0x00020000, 0x08020820,
+ 0x08000000, 0x08000820, 0x00000020, 0x08000000,
+ 0x00020020, 0x08020000, 0x08020820, 0x00020800,
+ 0x08020800, 0x00020820, 0x00000800, 0x00000020,
+ 0x08020000, 0x08000020, 0x08000800, 0x00000820,
+ 0x00020800, 0x00020020, 0x08020020, 0x08020800,
+ 0x00000820, 0x00000000, 0x00000000, 0x08020020,
+ 0x08000020, 0x08000800, 0x00020820, 0x00020000,
+ 0x00020820, 0x00020000, 0x08020800, 0x00000800,
+ 0x00000020, 0x08020020, 0x00000800, 0x00020820,
+ 0x08000800, 0x00000020, 0x08000020, 0x08020000,
+ 0x08020020, 0x08000000, 0x00020000, 0x08000820,
+ 0x00000000, 0x08020820, 0x00020020, 0x08000020,
+ 0x08020000, 0x08000800, 0x08000820, 0x00000000,
+ 0x08020820, 0x00020800, 0x00020800, 0x00000820,
+ 0x00000820, 0x00020020, 0x08000000, 0x08020800
+ );
+
+ /**
+ * Test for engine validity
+ *
+ * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
+ *
+ * @see \phpseclib\Crypt\Base::isValidEngine()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ if ($this->key_length_max == 8) {
+ if ($engine == self::ENGINE_OPENSSL) {
+ $this->cipher_name_openssl_ecb = 'des-ecb';
+ $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
+ }
+ }
+
+ return parent::isValidEngine($engine);
+ }
+
+ /**
+ * Sets the key.
+ *
+ * Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
+ * only use the first eight, if $key has more then eight characters in it, and pad $key with the
+ * null byte if it is less then eight characters long.
+ *
+ * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
+ *
+ * If the key is not explicitly set, it'll be assumed to be all zero's.
+ *
+ * @see \phpseclib\Crypt\Base::setKey()
+ * @access public
+ * @param string $key
+ */
+ function setKey($key)
+ {
+ // We check/cut here only up to max length of the key.
+ // Key padding to the proper length will be done in _setupKey()
+ if (strlen($key) > $this->key_length_max) {
+ $key = substr($key, 0, $this->key_length_max);
+ }
+
+ // Sets the key
+ parent::setKey($key);
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @see \phpseclib\Crypt\Base::_encryptBlock()
+ * @see \phpseclib\Crypt\Base::encrypt()
+ * @see self::encrypt()
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _encryptBlock($in)
+ {
+ return $this->_processBlock($in, self::ENCRYPT);
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @see \phpseclib\Crypt\Base::_decryptBlock()
+ * @see \phpseclib\Crypt\Base::decrypt()
+ * @see self::decrypt()
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _decryptBlock($in)
+ {
+ return $this->_processBlock($in, self::DECRYPT);
+ }
+
+ /**
+ * Encrypts or decrypts a 64-bit block
+ *
+ * $mode should be either self::ENCRYPT or self::DECRYPT. See
+ * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
+ * idea of what this function does.
+ *
+ * @see self::_encryptBlock()
+ * @see self::_decryptBlock()
+ * @access private
+ * @param string $block
+ * @param int $mode
+ * @return string
+ */
+ function _processBlock($block, $mode)
+ {
+ static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
+ if (!$sbox1) {
+ $sbox1 = array_map("intval", $this->sbox1);
+ $sbox2 = array_map("intval", $this->sbox2);
+ $sbox3 = array_map("intval", $this->sbox3);
+ $sbox4 = array_map("intval", $this->sbox4);
+ $sbox5 = array_map("intval", $this->sbox5);
+ $sbox6 = array_map("intval", $this->sbox6);
+ $sbox7 = array_map("intval", $this->sbox7);
+ $sbox8 = array_map("intval", $this->sbox8);
+ /* Merge $shuffle with $[inv]ipmap */
+ for ($i = 0; $i < 256; ++$i) {
+ $shuffleip[] = $this->shuffle[$this->ipmap[$i]];
+ $shuffleinvip[] = $this->shuffle[$this->invipmap[$i]];
+ }
+ }
+
+ $keys = $this->keys[$mode];
+ $ki = -1;
+
+ // Do the initial IP permutation.
+ $t = unpack('Nl/Nr', $block);
+ list($l, $r) = array($t['l'], $t['r']);
+ $block = ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
+ ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
+ ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
+ ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
+ ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
+ ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
+ ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
+ ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
+
+ // Extract L0 and R0.
+ $t = unpack('Nl/Nr', $block);
+ list($l, $r) = array($t['l'], $t['r']);
+
+ for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
+ // Perform the 16 steps.
+ for ($i = 0; $i < 16; $i++) {
+ // start of "the Feistel (F) function" - see the following URL:
+ // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
+ // Merge key schedule.
+ $b1 = (($r >> 3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki];
+ $b2 = (($r >> 31) & 0x00000001) ^ ($r << 1) ^ $keys[++$ki];
+
+ // S-box indexing.
+ $t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
+ $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
+ $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^
+ $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ $l;
+ // end of "the Feistel (F) function"
+
+ $l = $r;
+ $r = $t;
+ }
+
+ // Last step should not permute L & R.
+ $t = $l;
+ $l = $r;
+ $r = $t;
+ }
+
+ // Perform the inverse IP permutation.
+ return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
+ ($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
+ ($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
+ ($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
+ ($shuffleinvip[($r >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
+ ($shuffleinvip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
+ ($shuffleinvip[ $r & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
+ ($shuffleinvip[ $l & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
+ }
+
+ /**
+ * Creates the key schedule
+ *
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) {
+ // already expanded
+ return;
+ }
+ $this->kl = array('key' => $this->key, 'des_rounds' => $this->des_rounds);
+
+ static $shifts = array( // number of key bits shifted per round
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+ );
+
+ static $pc1map = array(
+ 0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C,
+ 0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E,
+ 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C,
+ 0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E,
+ 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C,
+ 0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E,
+ 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C,
+ 0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E,
+ 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C,
+ 0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E,
+ 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C,
+ 0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E,
+ 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C,
+ 0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E,
+ 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C,
+ 0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E,
+ 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C,
+ 0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E,
+ 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C,
+ 0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E,
+ 0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC,
+ 0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE,
+ 0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC,
+ 0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE,
+ 0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC,
+ 0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE,
+ 0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC,
+ 0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE,
+ 0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC,
+ 0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE,
+ 0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC,
+ 0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE
+ );
+
+ // Mapping tables for the PC-2 transformation.
+ static $pc2mapc1 = array(
+ 0x00000000, 0x00000400, 0x00200000, 0x00200400,
+ 0x00000001, 0x00000401, 0x00200001, 0x00200401,
+ 0x02000000, 0x02000400, 0x02200000, 0x02200400,
+ 0x02000001, 0x02000401, 0x02200001, 0x02200401
+ );
+ static $pc2mapc2 = array(
+ 0x00000000, 0x00000800, 0x08000000, 0x08000800,
+ 0x00010000, 0x00010800, 0x08010000, 0x08010800,
+ 0x00000000, 0x00000800, 0x08000000, 0x08000800,
+ 0x00010000, 0x00010800, 0x08010000, 0x08010800,
+ 0x00000100, 0x00000900, 0x08000100, 0x08000900,
+ 0x00010100, 0x00010900, 0x08010100, 0x08010900,
+ 0x00000100, 0x00000900, 0x08000100, 0x08000900,
+ 0x00010100, 0x00010900, 0x08010100, 0x08010900,
+ 0x00000010, 0x00000810, 0x08000010, 0x08000810,
+ 0x00010010, 0x00010810, 0x08010010, 0x08010810,
+ 0x00000010, 0x00000810, 0x08000010, 0x08000810,
+ 0x00010010, 0x00010810, 0x08010010, 0x08010810,
+ 0x00000110, 0x00000910, 0x08000110, 0x08000910,
+ 0x00010110, 0x00010910, 0x08010110, 0x08010910,
+ 0x00000110, 0x00000910, 0x08000110, 0x08000910,
+ 0x00010110, 0x00010910, 0x08010110, 0x08010910,
+ 0x00040000, 0x00040800, 0x08040000, 0x08040800,
+ 0x00050000, 0x00050800, 0x08050000, 0x08050800,
+ 0x00040000, 0x00040800, 0x08040000, 0x08040800,
+ 0x00050000, 0x00050800, 0x08050000, 0x08050800,
+ 0x00040100, 0x00040900, 0x08040100, 0x08040900,
+ 0x00050100, 0x00050900, 0x08050100, 0x08050900,
+ 0x00040100, 0x00040900, 0x08040100, 0x08040900,
+ 0x00050100, 0x00050900, 0x08050100, 0x08050900,
+ 0x00040010, 0x00040810, 0x08040010, 0x08040810,
+ 0x00050010, 0x00050810, 0x08050010, 0x08050810,
+ 0x00040010, 0x00040810, 0x08040010, 0x08040810,
+ 0x00050010, 0x00050810, 0x08050010, 0x08050810,
+ 0x00040110, 0x00040910, 0x08040110, 0x08040910,
+ 0x00050110, 0x00050910, 0x08050110, 0x08050910,
+ 0x00040110, 0x00040910, 0x08040110, 0x08040910,
+ 0x00050110, 0x00050910, 0x08050110, 0x08050910,
+ 0x01000000, 0x01000800, 0x09000000, 0x09000800,
+ 0x01010000, 0x01010800, 0x09010000, 0x09010800,
+ 0x01000000, 0x01000800, 0x09000000, 0x09000800,
+ 0x01010000, 0x01010800, 0x09010000, 0x09010800,
+ 0x01000100, 0x01000900, 0x09000100, 0x09000900,
+ 0x01010100, 0x01010900, 0x09010100, 0x09010900,
+ 0x01000100, 0x01000900, 0x09000100, 0x09000900,
+ 0x01010100, 0x01010900, 0x09010100, 0x09010900,
+ 0x01000010, 0x01000810, 0x09000010, 0x09000810,
+ 0x01010010, 0x01010810, 0x09010010, 0x09010810,
+ 0x01000010, 0x01000810, 0x09000010, 0x09000810,
+ 0x01010010, 0x01010810, 0x09010010, 0x09010810,
+ 0x01000110, 0x01000910, 0x09000110, 0x09000910,
+ 0x01010110, 0x01010910, 0x09010110, 0x09010910,
+ 0x01000110, 0x01000910, 0x09000110, 0x09000910,
+ 0x01010110, 0x01010910, 0x09010110, 0x09010910,
+ 0x01040000, 0x01040800, 0x09040000, 0x09040800,
+ 0x01050000, 0x01050800, 0x09050000, 0x09050800,
+ 0x01040000, 0x01040800, 0x09040000, 0x09040800,
+ 0x01050000, 0x01050800, 0x09050000, 0x09050800,
+ 0x01040100, 0x01040900, 0x09040100, 0x09040900,
+ 0x01050100, 0x01050900, 0x09050100, 0x09050900,
+ 0x01040100, 0x01040900, 0x09040100, 0x09040900,
+ 0x01050100, 0x01050900, 0x09050100, 0x09050900,
+ 0x01040010, 0x01040810, 0x09040010, 0x09040810,
+ 0x01050010, 0x01050810, 0x09050010, 0x09050810,
+ 0x01040010, 0x01040810, 0x09040010, 0x09040810,
+ 0x01050010, 0x01050810, 0x09050010, 0x09050810,
+ 0x01040110, 0x01040910, 0x09040110, 0x09040910,
+ 0x01050110, 0x01050910, 0x09050110, 0x09050910,
+ 0x01040110, 0x01040910, 0x09040110, 0x09040910,
+ 0x01050110, 0x01050910, 0x09050110, 0x09050910
+ );
+ static $pc2mapc3 = array(
+ 0x00000000, 0x00000004, 0x00001000, 0x00001004,
+ 0x00000000, 0x00000004, 0x00001000, 0x00001004,
+ 0x10000000, 0x10000004, 0x10001000, 0x10001004,
+ 0x10000000, 0x10000004, 0x10001000, 0x10001004,
+ 0x00000020, 0x00000024, 0x00001020, 0x00001024,
+ 0x00000020, 0x00000024, 0x00001020, 0x00001024,
+ 0x10000020, 0x10000024, 0x10001020, 0x10001024,
+ 0x10000020, 0x10000024, 0x10001020, 0x10001024,
+ 0x00080000, 0x00080004, 0x00081000, 0x00081004,
+ 0x00080000, 0x00080004, 0x00081000, 0x00081004,
+ 0x10080000, 0x10080004, 0x10081000, 0x10081004,
+ 0x10080000, 0x10080004, 0x10081000, 0x10081004,
+ 0x00080020, 0x00080024, 0x00081020, 0x00081024,
+ 0x00080020, 0x00080024, 0x00081020, 0x00081024,
+ 0x10080020, 0x10080024, 0x10081020, 0x10081024,
+ 0x10080020, 0x10080024, 0x10081020, 0x10081024,
+ 0x20000000, 0x20000004, 0x20001000, 0x20001004,
+ 0x20000000, 0x20000004, 0x20001000, 0x20001004,
+ 0x30000000, 0x30000004, 0x30001000, 0x30001004,
+ 0x30000000, 0x30000004, 0x30001000, 0x30001004,
+ 0x20000020, 0x20000024, 0x20001020, 0x20001024,
+ 0x20000020, 0x20000024, 0x20001020, 0x20001024,
+ 0x30000020, 0x30000024, 0x30001020, 0x30001024,
+ 0x30000020, 0x30000024, 0x30001020, 0x30001024,
+ 0x20080000, 0x20080004, 0x20081000, 0x20081004,
+ 0x20080000, 0x20080004, 0x20081000, 0x20081004,
+ 0x30080000, 0x30080004, 0x30081000, 0x30081004,
+ 0x30080000, 0x30080004, 0x30081000, 0x30081004,
+ 0x20080020, 0x20080024, 0x20081020, 0x20081024,
+ 0x20080020, 0x20080024, 0x20081020, 0x20081024,
+ 0x30080020, 0x30080024, 0x30081020, 0x30081024,
+ 0x30080020, 0x30080024, 0x30081020, 0x30081024,
+ 0x00000002, 0x00000006, 0x00001002, 0x00001006,
+ 0x00000002, 0x00000006, 0x00001002, 0x00001006,
+ 0x10000002, 0x10000006, 0x10001002, 0x10001006,
+ 0x10000002, 0x10000006, 0x10001002, 0x10001006,
+ 0x00000022, 0x00000026, 0x00001022, 0x00001026,
+ 0x00000022, 0x00000026, 0x00001022, 0x00001026,
+ 0x10000022, 0x10000026, 0x10001022, 0x10001026,
+ 0x10000022, 0x10000026, 0x10001022, 0x10001026,
+ 0x00080002, 0x00080006, 0x00081002, 0x00081006,
+ 0x00080002, 0x00080006, 0x00081002, 0x00081006,
+ 0x10080002, 0x10080006, 0x10081002, 0x10081006,
+ 0x10080002, 0x10080006, 0x10081002, 0x10081006,
+ 0x00080022, 0x00080026, 0x00081022, 0x00081026,
+ 0x00080022, 0x00080026, 0x00081022, 0x00081026,
+ 0x10080022, 0x10080026, 0x10081022, 0x10081026,
+ 0x10080022, 0x10080026, 0x10081022, 0x10081026,
+ 0x20000002, 0x20000006, 0x20001002, 0x20001006,
+ 0x20000002, 0x20000006, 0x20001002, 0x20001006,
+ 0x30000002, 0x30000006, 0x30001002, 0x30001006,
+ 0x30000002, 0x30000006, 0x30001002, 0x30001006,
+ 0x20000022, 0x20000026, 0x20001022, 0x20001026,
+ 0x20000022, 0x20000026, 0x20001022, 0x20001026,
+ 0x30000022, 0x30000026, 0x30001022, 0x30001026,
+ 0x30000022, 0x30000026, 0x30001022, 0x30001026,
+ 0x20080002, 0x20080006, 0x20081002, 0x20081006,
+ 0x20080002, 0x20080006, 0x20081002, 0x20081006,
+ 0x30080002, 0x30080006, 0x30081002, 0x30081006,
+ 0x30080002, 0x30080006, 0x30081002, 0x30081006,
+ 0x20080022, 0x20080026, 0x20081022, 0x20081026,
+ 0x20080022, 0x20080026, 0x20081022, 0x20081026,
+ 0x30080022, 0x30080026, 0x30081022, 0x30081026,
+ 0x30080022, 0x30080026, 0x30081022, 0x30081026
+ );
+ static $pc2mapc4 = array(
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
+ 0x00000000, 0x00100000, 0x00000008, 0x00100008,
+ 0x00000200, 0x00100200, 0x00000208, 0x00100208,
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
+ 0x04000000, 0x04100000, 0x04000008, 0x04100008,
+ 0x04000200, 0x04100200, 0x04000208, 0x04100208,
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
+ 0x00002000, 0x00102000, 0x00002008, 0x00102008,
+ 0x00002200, 0x00102200, 0x00002208, 0x00102208,
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
+ 0x04002000, 0x04102000, 0x04002008, 0x04102008,
+ 0x04002200, 0x04102200, 0x04002208, 0x04102208,
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208,
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208,
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
+ 0x00020000, 0x00120000, 0x00020008, 0x00120008,
+ 0x00020200, 0x00120200, 0x00020208, 0x00120208,
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
+ 0x04020000, 0x04120000, 0x04020008, 0x04120008,
+ 0x04020200, 0x04120200, 0x04020208, 0x04120208,
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
+ 0x00022000, 0x00122000, 0x00022008, 0x00122008,
+ 0x00022200, 0x00122200, 0x00022208, 0x00122208,
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208,
+ 0x04022000, 0x04122000, 0x04022008, 0x04122008,
+ 0x04022200, 0x04122200, 0x04022208, 0x04122208
+ );
+ static $pc2mapd1 = array(
+ 0x00000000, 0x00000001, 0x08000000, 0x08000001,
+ 0x00200000, 0x00200001, 0x08200000, 0x08200001,
+ 0x00000002, 0x00000003, 0x08000002, 0x08000003,
+ 0x00200002, 0x00200003, 0x08200002, 0x08200003
+ );
+ static $pc2mapd2 = array(
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
+ 0x00000000, 0x00100000, 0x00000800, 0x00100800,
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
+ 0x04000000, 0x04100000, 0x04000800, 0x04100800,
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
+ 0x00000004, 0x00100004, 0x00000804, 0x00100804,
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
+ 0x04000004, 0x04100004, 0x04000804, 0x04100804,
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
+ 0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
+ 0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
+ 0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
+ 0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
+ 0x00020000, 0x00120000, 0x00020800, 0x00120800,
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
+ 0x04020000, 0x04120000, 0x04020800, 0x04120800,
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
+ 0x00020004, 0x00120004, 0x00020804, 0x00120804,
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
+ 0x04020004, 0x04120004, 0x04020804, 0x04120804,
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
+ 0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
+ 0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
+ 0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
+ 0x04020204, 0x04120204, 0x04020A04, 0x04120A04
+ );
+ static $pc2mapd3 = array(
+ 0x00000000, 0x00010000, 0x02000000, 0x02010000,
+ 0x00000020, 0x00010020, 0x02000020, 0x02010020,
+ 0x00040000, 0x00050000, 0x02040000, 0x02050000,
+ 0x00040020, 0x00050020, 0x02040020, 0x02050020,
+ 0x00002000, 0x00012000, 0x02002000, 0x02012000,
+ 0x00002020, 0x00012020, 0x02002020, 0x02012020,
+ 0x00042000, 0x00052000, 0x02042000, 0x02052000,
+ 0x00042020, 0x00052020, 0x02042020, 0x02052020,
+ 0x00000000, 0x00010000, 0x02000000, 0x02010000,
+ 0x00000020, 0x00010020, 0x02000020, 0x02010020,
+ 0x00040000, 0x00050000, 0x02040000, 0x02050000,
+ 0x00040020, 0x00050020, 0x02040020, 0x02050020,
+ 0x00002000, 0x00012000, 0x02002000, 0x02012000,
+ 0x00002020, 0x00012020, 0x02002020, 0x02012020,
+ 0x00042000, 0x00052000, 0x02042000, 0x02052000,
+ 0x00042020, 0x00052020, 0x02042020, 0x02052020,
+ 0x00000010, 0x00010010, 0x02000010, 0x02010010,
+ 0x00000030, 0x00010030, 0x02000030, 0x02010030,
+ 0x00040010, 0x00050010, 0x02040010, 0x02050010,
+ 0x00040030, 0x00050030, 0x02040030, 0x02050030,
+ 0x00002010, 0x00012010, 0x02002010, 0x02012010,
+ 0x00002030, 0x00012030, 0x02002030, 0x02012030,
+ 0x00042010, 0x00052010, 0x02042010, 0x02052010,
+ 0x00042030, 0x00052030, 0x02042030, 0x02052030,
+ 0x00000010, 0x00010010, 0x02000010, 0x02010010,
+ 0x00000030, 0x00010030, 0x02000030, 0x02010030,
+ 0x00040010, 0x00050010, 0x02040010, 0x02050010,
+ 0x00040030, 0x00050030, 0x02040030, 0x02050030,
+ 0x00002010, 0x00012010, 0x02002010, 0x02012010,
+ 0x00002030, 0x00012030, 0x02002030, 0x02012030,
+ 0x00042010, 0x00052010, 0x02042010, 0x02052010,
+ 0x00042030, 0x00052030, 0x02042030, 0x02052030,
+ 0x20000000, 0x20010000, 0x22000000, 0x22010000,
+ 0x20000020, 0x20010020, 0x22000020, 0x22010020,
+ 0x20040000, 0x20050000, 0x22040000, 0x22050000,
+ 0x20040020, 0x20050020, 0x22040020, 0x22050020,
+ 0x20002000, 0x20012000, 0x22002000, 0x22012000,
+ 0x20002020, 0x20012020, 0x22002020, 0x22012020,
+ 0x20042000, 0x20052000, 0x22042000, 0x22052000,
+ 0x20042020, 0x20052020, 0x22042020, 0x22052020,
+ 0x20000000, 0x20010000, 0x22000000, 0x22010000,
+ 0x20000020, 0x20010020, 0x22000020, 0x22010020,
+ 0x20040000, 0x20050000, 0x22040000, 0x22050000,
+ 0x20040020, 0x20050020, 0x22040020, 0x22050020,
+ 0x20002000, 0x20012000, 0x22002000, 0x22012000,
+ 0x20002020, 0x20012020, 0x22002020, 0x22012020,
+ 0x20042000, 0x20052000, 0x22042000, 0x22052000,
+ 0x20042020, 0x20052020, 0x22042020, 0x22052020,
+ 0x20000010, 0x20010010, 0x22000010, 0x22010010,
+ 0x20000030, 0x20010030, 0x22000030, 0x22010030,
+ 0x20040010, 0x20050010, 0x22040010, 0x22050010,
+ 0x20040030, 0x20050030, 0x22040030, 0x22050030,
+ 0x20002010, 0x20012010, 0x22002010, 0x22012010,
+ 0x20002030, 0x20012030, 0x22002030, 0x22012030,
+ 0x20042010, 0x20052010, 0x22042010, 0x22052010,
+ 0x20042030, 0x20052030, 0x22042030, 0x22052030,
+ 0x20000010, 0x20010010, 0x22000010, 0x22010010,
+ 0x20000030, 0x20010030, 0x22000030, 0x22010030,
+ 0x20040010, 0x20050010, 0x22040010, 0x22050010,
+ 0x20040030, 0x20050030, 0x22040030, 0x22050030,
+ 0x20002010, 0x20012010, 0x22002010, 0x22012010,
+ 0x20002030, 0x20012030, 0x22002030, 0x22012030,
+ 0x20042010, 0x20052010, 0x22042010, 0x22052010,
+ 0x20042030, 0x20052030, 0x22042030, 0x22052030
+ );
+ static $pc2mapd4 = array(
+ 0x00000000, 0x00000400, 0x01000000, 0x01000400,
+ 0x00000000, 0x00000400, 0x01000000, 0x01000400,
+ 0x00000100, 0x00000500, 0x01000100, 0x01000500,
+ 0x00000100, 0x00000500, 0x01000100, 0x01000500,
+ 0x10000000, 0x10000400, 0x11000000, 0x11000400,
+ 0x10000000, 0x10000400, 0x11000000, 0x11000400,
+ 0x10000100, 0x10000500, 0x11000100, 0x11000500,
+ 0x10000100, 0x10000500, 0x11000100, 0x11000500,
+ 0x00080000, 0x00080400, 0x01080000, 0x01080400,
+ 0x00080000, 0x00080400, 0x01080000, 0x01080400,
+ 0x00080100, 0x00080500, 0x01080100, 0x01080500,
+ 0x00080100, 0x00080500, 0x01080100, 0x01080500,
+ 0x10080000, 0x10080400, 0x11080000, 0x11080400,
+ 0x10080000, 0x10080400, 0x11080000, 0x11080400,
+ 0x10080100, 0x10080500, 0x11080100, 0x11080500,
+ 0x10080100, 0x10080500, 0x11080100, 0x11080500,
+ 0x00000008, 0x00000408, 0x01000008, 0x01000408,
+ 0x00000008, 0x00000408, 0x01000008, 0x01000408,
+ 0x00000108, 0x00000508, 0x01000108, 0x01000508,
+ 0x00000108, 0x00000508, 0x01000108, 0x01000508,
+ 0x10000008, 0x10000408, 0x11000008, 0x11000408,
+ 0x10000008, 0x10000408, 0x11000008, 0x11000408,
+ 0x10000108, 0x10000508, 0x11000108, 0x11000508,
+ 0x10000108, 0x10000508, 0x11000108, 0x11000508,
+ 0x00080008, 0x00080408, 0x01080008, 0x01080408,
+ 0x00080008, 0x00080408, 0x01080008, 0x01080408,
+ 0x00080108, 0x00080508, 0x01080108, 0x01080508,
+ 0x00080108, 0x00080508, 0x01080108, 0x01080508,
+ 0x10080008, 0x10080408, 0x11080008, 0x11080408,
+ 0x10080008, 0x10080408, 0x11080008, 0x11080408,
+ 0x10080108, 0x10080508, 0x11080108, 0x11080508,
+ 0x10080108, 0x10080508, 0x11080108, 0x11080508,
+ 0x00001000, 0x00001400, 0x01001000, 0x01001400,
+ 0x00001000, 0x00001400, 0x01001000, 0x01001400,
+ 0x00001100, 0x00001500, 0x01001100, 0x01001500,
+ 0x00001100, 0x00001500, 0x01001100, 0x01001500,
+ 0x10001000, 0x10001400, 0x11001000, 0x11001400,
+ 0x10001000, 0x10001400, 0x11001000, 0x11001400,
+ 0x10001100, 0x10001500, 0x11001100, 0x11001500,
+ 0x10001100, 0x10001500, 0x11001100, 0x11001500,
+ 0x00081000, 0x00081400, 0x01081000, 0x01081400,
+ 0x00081000, 0x00081400, 0x01081000, 0x01081400,
+ 0x00081100, 0x00081500, 0x01081100, 0x01081500,
+ 0x00081100, 0x00081500, 0x01081100, 0x01081500,
+ 0x10081000, 0x10081400, 0x11081000, 0x11081400,
+ 0x10081000, 0x10081400, 0x11081000, 0x11081400,
+ 0x10081100, 0x10081500, 0x11081100, 0x11081500,
+ 0x10081100, 0x10081500, 0x11081100, 0x11081500,
+ 0x00001008, 0x00001408, 0x01001008, 0x01001408,
+ 0x00001008, 0x00001408, 0x01001008, 0x01001408,
+ 0x00001108, 0x00001508, 0x01001108, 0x01001508,
+ 0x00001108, 0x00001508, 0x01001108, 0x01001508,
+ 0x10001008, 0x10001408, 0x11001008, 0x11001408,
+ 0x10001008, 0x10001408, 0x11001008, 0x11001408,
+ 0x10001108, 0x10001508, 0x11001108, 0x11001508,
+ 0x10001108, 0x10001508, 0x11001108, 0x11001508,
+ 0x00081008, 0x00081408, 0x01081008, 0x01081408,
+ 0x00081008, 0x00081408, 0x01081008, 0x01081408,
+ 0x00081108, 0x00081508, 0x01081108, 0x01081508,
+ 0x00081108, 0x00081508, 0x01081108, 0x01081508,
+ 0x10081008, 0x10081408, 0x11081008, 0x11081408,
+ 0x10081008, 0x10081408, 0x11081008, 0x11081408,
+ 0x10081108, 0x10081508, 0x11081108, 0x11081508,
+ 0x10081108, 0x10081508, 0x11081108, 0x11081508
+ );
+
+ $keys = array();
+ for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
+ // pad the key and remove extra characters as appropriate.
+ $key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0");
+
+ // Perform the PC/1 transformation and compute C and D.
+ $t = unpack('Nl/Nr', $key);
+ list($l, $r) = array($t['l'], $t['r']);
+ $key = ($this->shuffle[$pc1map[ $r & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") |
+ ($this->shuffle[$pc1map[($r >> 8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") |
+ ($this->shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") |
+ ($this->shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") |
+ ($this->shuffle[$pc1map[ $l & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") |
+ ($this->shuffle[$pc1map[($l >> 8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") |
+ ($this->shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") |
+ ($this->shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00");
+ $key = unpack('Nc/Nd', $key);
+ $c = ( $key['c'] >> 4) & 0x0FFFFFFF;
+ $d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F);
+
+ $keys[$des_round] = array(
+ self::ENCRYPT => array(),
+ self::DECRYPT => array_fill(0, 32, 0)
+ );
+ for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) {
+ $c <<= $shifts[$i];
+ $c = ($c | ($c >> 28)) & 0x0FFFFFFF;
+ $d <<= $shifts[$i];
+ $d = ($d | ($d >> 28)) & 0x0FFFFFFF;
+
+ // Perform the PC-2 transformation.
+ $cp = $pc2mapc1[ $c >> 24 ] | $pc2mapc2[($c >> 16) & 0xFF] |
+ $pc2mapc3[($c >> 8) & 0xFF] | $pc2mapc4[ $c & 0xFF];
+ $dp = $pc2mapd1[ $d >> 24 ] | $pc2mapd2[($d >> 16) & 0xFF] |
+ $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF];
+
+ // Reorder: odd bytes/even bytes. Push the result in key schedule.
+ $val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) |
+ (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF);
+ $val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) |
+ (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF);
+ $keys[$des_round][self::ENCRYPT][ ] = $val1;
+ $keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
+ $keys[$des_round][self::ENCRYPT][ ] = $val2;
+ $keys[$des_round][self::DECRYPT][$ki ] = $val2;
+ }
+ }
+
+ switch ($this->des_rounds) {
+ case 3: // 3DES keys
+ $this->keys = array(
+ self::ENCRYPT => array_merge(
+ $keys[0][self::ENCRYPT],
+ $keys[1][self::DECRYPT],
+ $keys[2][self::ENCRYPT]
+ ),
+ self::DECRYPT => array_merge(
+ $keys[2][self::DECRYPT],
+ $keys[1][self::ENCRYPT],
+ $keys[0][self::DECRYPT]
+ )
+ );
+ break;
+ // case 1: // DES keys
+ default:
+ $this->keys = array(
+ self::ENCRYPT => $keys[0][self::ENCRYPT],
+ self::DECRYPT => $keys[0][self::DECRYPT]
+ );
+ }
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ $lambda_functions =& self::_getLambdaFunctions();
+
+ // Engine configuration for:
+ // - DES ($des_rounds == 1) or
+ // - 3DES ($des_rounds == 3)
+ $des_rounds = $this->des_rounds;
+
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
+ // (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
+ // (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
+ $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
+
+ // Generation of a unique hash for our generated code
+ $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
+ if ($gen_hi_opt_code) {
+ // For hi-optimized code, we create for each combination of
+ // $mode, $des_rounds and $this->key its own encrypt/decrypt function.
+ // After max 10 hi-optimized functions, we create generic
+ // (still very fast.. but not ultra) functions for each $mode/$des_rounds
+ // Currently 2 * 5 generic functions will be then max. possible.
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
+ }
+
+ // Is there a re-usable $lambda_functions in there? If not, we have to create it.
+ if (!isset($lambda_functions[$code_hash])) {
+ // Init code for both, encrypt and decrypt.
+ $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
+ if (!$sbox1) {
+ $sbox1 = array_map("intval", $self->sbox1);
+ $sbox2 = array_map("intval", $self->sbox2);
+ $sbox3 = array_map("intval", $self->sbox3);
+ $sbox4 = array_map("intval", $self->sbox4);
+ $sbox5 = array_map("intval", $self->sbox5);
+ $sbox6 = array_map("intval", $self->sbox6);
+ $sbox7 = array_map("intval", $self->sbox7);
+ $sbox8 = array_map("intval", $self->sbox8);'
+ /* Merge $shuffle with $[inv]ipmap */ . '
+ for ($i = 0; $i < 256; ++$i) {
+ $shuffleip[] = $self->shuffle[$self->ipmap[$i]];
+ $shuffleinvip[] = $self->shuffle[$self->invipmap[$i]];
+ }
+ }
+ ';
+
+ switch (true) {
+ case $gen_hi_opt_code:
+ // In Hi-optimized code mode, we use our [3]DES key schedule as hardcoded integers.
+ // No futher initialisation of the $keys schedule is necessary.
+ // That is the extra performance boost.
+ $k = array(
+ self::ENCRYPT => $this->keys[self::ENCRYPT],
+ self::DECRYPT => $this->keys[self::DECRYPT]
+ );
+ $init_encrypt = '';
+ $init_decrypt = '';
+ break;
+ default:
+ // In generic optimized code mode, we have to use, as the best compromise [currently],
+ // our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
+ $k = array(
+ self::ENCRYPT => array(),
+ self::DECRYPT => array()
+ );
+ for ($i = 0, $c = count($this->keys[self::ENCRYPT]); $i < $c; ++$i) {
+ $k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
+ $k[self::DECRYPT][$i] = '$kd[' . $i . ']';
+ }
+ $init_encrypt = '$ke = $self->keys[$self::ENCRYPT];';
+ $init_decrypt = '$kd = $self->keys[$self::DECRYPT];';
+ break;
+ }
+
+ // Creating code for en- and decryption.
+ $crypt_block = array();
+ foreach (array(self::ENCRYPT, self::DECRYPT) as $c) {
+ /* Do the initial IP permutation. */
+ $crypt_block[$c] = '
+ $in = unpack("N*", $in);
+ $l = $in[1];
+ $r = $in[2];
+ $in = unpack("N*",
+ ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
+ ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
+ ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
+ ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
+ ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
+ ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
+ ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
+ ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01")
+ );
+ ' . /* Extract L0 and R0 */ '
+ $l = $in[1];
+ $r = $in[2];
+ ';
+
+ $l = '$l';
+ $r = '$r';
+
+ // Perform DES or 3DES.
+ for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
+ // Perform the 16 steps.
+ for ($i = 0; $i < 16; ++$i) {
+ // start of "the Feistel (F) function" - see the following URL:
+ // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
+ // Merge key schedule.
+ $crypt_block[$c].= '
+ $b1 = ((' . $r . ' >> 3) & 0x1FFFFFFF) ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
+ $b2 = ((' . $r . ' >> 31) & 0x00000001) ^ (' . $r . ' << 1) ^ ' . $k[$c][++$ki] . ';' .
+ /* S-box indexing. */
+ $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
+ $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
+ $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^
+ $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ ' . $l . ';
+ ';
+ // end of "the Feistel (F) function"
+
+ // swap L & R
+ list($l, $r) = array($r, $l);
+ }
+ list($l, $r) = array($r, $l);
+ }
+
+ // Perform the inverse IP permutation.
+ $crypt_block[$c].= '$in =
+ ($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
+ ($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
+ ($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
+ ($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
+ ($shuffleinvip[($l >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
+ ($shuffleinvip[($r >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
+ ($shuffleinvip[ $l & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
+ ($shuffleinvip[ $r & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
+ ';
+ }
+
+ // Creates the inline-crypt function
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
+ array(
+ 'init_crypt' => $init_crypt,
+ 'init_encrypt' => $init_encrypt,
+ 'init_decrypt' => $init_decrypt,
+ 'encrypt_block' => $crypt_block[self::ENCRYPT],
+ 'decrypt_block' => $crypt_block[self::DECRYPT]
+ )
+ );
+ }
+
+ // Set the inline-crypt function as callback in: $this->inline_crypt
+ $this->inline_crypt = $lambda_functions[$code_hash];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
+ *
+ * Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
+ *
+ * md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
+ *
+ * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
+ * the hash. If no valid algorithm is provided, sha1 will be used.
+ *
+ * PHP version 5
+ *
+ * {@internal The variable names are the same as those in
+ * {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $hash = new \phpseclib\Crypt\Hash('sha1');
+ *
+ * $hash->setKey('abcdefg');
+ *
+ * echo base64_encode($hash->hash('abcdefg'));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package Hash
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+use phpseclib\Math\BigInteger;
+
+/**
+ * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
+ *
+ * @package Hash
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class Hash
+{
+ /**#@+
+ * @access private
+ * @see \phpseclib\Crypt\Hash::__construct()
+ */
+ /**
+ * Toggles the internal implementation
+ */
+ const MODE_INTERNAL = 1;
+ /**
+ * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
+ */
+ const MODE_MHASH = 2;
+ /**
+ * Toggles the hash() implementation, which works on PHP 5.1.2+.
+ */
+ const MODE_HASH = 3;
+ /**#@-*/
+
+ /**
+ * Hash Parameter
+ *
+ * @see self::setHash()
+ * @var int
+ * @access private
+ */
+ var $hashParam;
+
+ /**
+ * Byte-length of compression blocks / key (Internal HMAC)
+ *
+ * @see self::setAlgorithm()
+ * @var int
+ * @access private
+ */
+ var $b;
+
+ /**
+ * Byte-length of hash output (Internal HMAC)
+ *
+ * @see self::setHash()
+ * @var int
+ * @access private
+ */
+ var $l = false;
+
+ /**
+ * Hash Algorithm
+ *
+ * @see self::setHash()
+ * @var string
+ * @access private
+ */
+ var $hash;
+
+ /**
+ * Key
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $key = false;
+
+ /**
+ * Computed Key
+ *
+ * @see self::_computeKey()
+ * @var string
+ * @access private
+ */
+ var $computedKey = false;
+
+ /**
+ * Outer XOR (Internal HMAC)
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $opad;
+
+ /**
+ * Inner XOR (Internal HMAC)
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $ipad;
+
+ /**
+ * Engine
+ *
+ * @see self::setHash()
+ * @var string
+ * @access private
+ */
+ var $engine;
+
+ /**
+ * Default Constructor.
+ *
+ * @param string $hash
+ * @return \phpseclib\Crypt\Hash
+ * @access public
+ */
+ function __construct($hash = 'sha1')
+ {
+ if (!defined('CRYPT_HASH_MODE')) {
+ switch (true) {
+ case extension_loaded('hash'):
+ define('CRYPT_HASH_MODE', self::MODE_HASH);
+ break;
+ case extension_loaded('mhash'):
+ define('CRYPT_HASH_MODE', self::MODE_MHASH);
+ break;
+ default:
+ define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
+ }
+ }
+
+ $this->setHash($hash);
+ }
+
+ /**
+ * Sets the key for HMACs
+ *
+ * Keys can be of any length.
+ *
+ * @access public
+ * @param string $key
+ */
+ function setKey($key = false)
+ {
+ $this->key = $key;
+ $this->_computeKey();
+ }
+
+ /**
+ * Pre-compute the key used by the HMAC
+ *
+ * Quoting http://tools.ietf.org/html/rfc2104#section-2, "Applications that use keys longer than B bytes
+ * will first hash the key using H and then use the resultant L byte string as the actual key to HMAC."
+ *
+ * As documented in https://www.reddit.com/r/PHP/comments/9nct2l/symfonypolyfill_hash_pbkdf2_correct_fix_for/
+ * when doing an HMAC multiple times it's faster to compute the hash once instead of computing it during
+ * every call
+ *
+ * @access private
+ */
+ function _computeKey()
+ {
+ if ($this->key === false) {
+ $this->computedKey = false;
+ return;
+ }
+
+ if (strlen($this->key) <= $this->b) {
+ $this->computedKey = $this->key;
+ return;
+ }
+
+ switch ($this->engine) {
+ case self::MODE_MHASH:
+ $this->computedKey = mhash($this->hash, $this->key);
+ break;
+ case self::MODE_HASH:
+ $this->computedKey = hash($this->hash, $this->key, true);
+ break;
+ case self::MODE_INTERNAL:
+ $this->computedKey = call_user_func($this->hash, $this->key);
+ }
+ }
+
+ /**
+ * Gets the hash function.
+ *
+ * As set by the constructor or by the setHash() method.
+ *
+ * @access public
+ * @return string
+ */
+ function getHash()
+ {
+ return $this->hashParam;
+ }
+
+ /**
+ * Sets the hash function.
+ *
+ * @access public
+ * @param string $hash
+ */
+ function setHash($hash)
+ {
+ $this->hashParam = $hash = strtolower($hash);
+ switch ($hash) {
+ case 'md5-96':
+ case 'sha1-96':
+ case 'sha256-96':
+ case 'sha512-96':
+ $hash = substr($hash, 0, -3);
+ $this->l = 12; // 96 / 8 = 12
+ break;
+ case 'md2':
+ case 'md5':
+ $this->l = 16;
+ break;
+ case 'sha1':
+ $this->l = 20;
+ break;
+ case 'sha256':
+ $this->l = 32;
+ break;
+ case 'sha384':
+ $this->l = 48;
+ break;
+ case 'sha512':
+ $this->l = 64;
+ }
+
+ switch ($hash) {
+ case 'md2-96':
+ case 'md2':
+ $this->b = 16;
+ case 'md5-96':
+ case 'sha1-96':
+ case 'sha224-96':
+ case 'sha256-96':
+ case 'md2':
+ case 'md5':
+ case 'sha1':
+ case 'sha224':
+ case 'sha256':
+ $this->b = 64;
+ break;
+ default:
+ $this->b = 128;
+ }
+
+ switch ($hash) {
+ case 'md2':
+ $this->engine = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ?
+ self::MODE_HASH : self::MODE_INTERNAL;
+ break;
+ case 'sha384':
+ case 'sha512':
+ $this->engine = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
+ break;
+ default:
+ $this->engine = CRYPT_HASH_MODE;
+ }
+
+ switch ($this->engine) {
+ case self::MODE_MHASH:
+ switch ($hash) {
+ case 'md5':
+ $this->hash = MHASH_MD5;
+ break;
+ case 'sha256':
+ $this->hash = MHASH_SHA256;
+ break;
+ case 'sha1':
+ default:
+ $this->hash = MHASH_SHA1;
+ }
+ $this->_computeKey(self::MODE_MHASH);
+ return;
+ case self::MODE_HASH:
+ switch ($hash) {
+ case 'md5':
+ $this->hash = 'md5';
+ return;
+ case 'md2':
+ case 'sha256':
+ case 'sha384':
+ case 'sha512':
+ $this->hash = $hash;
+ return;
+ case 'sha1':
+ default:
+ $this->hash = 'sha1';
+ }
+ $this->_computeKey(self::MODE_HASH);
+ return;
+ }
+
+ switch ($hash) {
+ case 'md2':
+ $this->hash = array($this, '_md2');
+ break;
+ case 'md5':
+ $this->hash = array($this, '_md5');
+ break;
+ case 'sha256':
+ $this->hash = array($this, '_sha256');
+ break;
+ case 'sha384':
+ case 'sha512':
+ $this->hash = array($this, '_sha512');
+ break;
+ case 'sha1':
+ default:
+ $this->hash = array($this, '_sha1');
+ }
+
+ $this->ipad = str_repeat(chr(0x36), $this->b);
+ $this->opad = str_repeat(chr(0x5C), $this->b);
+
+ $this->_computeKey(self::MODE_INTERNAL);
+ }
+
+ /**
+ * Compute the HMAC.
+ *
+ * @access public
+ * @param string $text
+ * @return string
+ */
+ function hash($text)
+ {
+ if (!empty($this->key) || is_string($this->key)) {
+ switch ($this->engine) {
+ case self::MODE_MHASH:
+ $output = mhash($this->hash, $text, $this->computedKey);
+ break;
+ case self::MODE_HASH:
+ $output = hash_hmac($this->hash, $text, $this->computedKey, true);
+ break;
+ case self::MODE_INTERNAL:
+ $key = str_pad($this->computedKey, $this->b, chr(0)); // step 1
+ $temp = $this->ipad ^ $key; // step 2
+ $temp .= $text; // step 3
+ $temp = call_user_func($this->hash, $temp); // step 4
+ $output = $this->opad ^ $key; // step 5
+ $output.= $temp; // step 6
+ $output = call_user_func($this->hash, $output); // step 7
+ }
+ } else {
+ switch ($this->engine) {
+ case self::MODE_MHASH:
+ $output = mhash($this->hash, $text);
+ break;
+ case self::MODE_HASH:
+ $output = hash($this->hash, $text, true);
+ break;
+ case self::MODE_INTERNAL:
+ $output = call_user_func($this->hash, $text);
+ }
+ }
+
+ return substr($output, 0, $this->l);
+ }
+
+ /**
+ * Returns the hash length (in bytes)
+ *
+ * @access public
+ * @return int
+ */
+ function getLength()
+ {
+ return $this->l;
+ }
+
+ /**
+ * Wrapper for MD5
+ *
+ * @access private
+ * @param string $m
+ */
+ function _md5($m)
+ {
+ return pack('H*', md5($m));
+ }
+
+ /**
+ * Wrapper for SHA1
+ *
+ * @access private
+ * @param string $m
+ */
+ function _sha1($m)
+ {
+ return pack('H*', sha1($m));
+ }
+
+ /**
+ * Pure-PHP implementation of MD2
+ *
+ * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
+ *
+ * @access private
+ * @param string $m
+ */
+ function _md2($m)
+ {
+ static $s = array(
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+ );
+
+ // Step 1. Append Padding Bytes
+ $pad = 16 - (strlen($m) & 0xF);
+ $m.= str_repeat(chr($pad), $pad);
+
+ $length = strlen($m);
+
+ // Step 2. Append Checksum
+ $c = str_repeat(chr(0), 16);
+ $l = chr(0);
+ for ($i = 0; $i < $length; $i+= 16) {
+ for ($j = 0; $j < 16; $j++) {
+ // RFC1319 incorrectly states that C[j] should be set to S[c xor L]
+ //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
+ // per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
+ $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
+ $l = $c[$j];
+ }
+ }
+ $m.= $c;
+
+ $length+= 16;
+
+ // Step 3. Initialize MD Buffer
+ $x = str_repeat(chr(0), 48);
+
+ // Step 4. Process Message in 16-Byte Blocks
+ for ($i = 0; $i < $length; $i+= 16) {
+ for ($j = 0; $j < 16; $j++) {
+ $x[$j + 16] = $m[$i + $j];
+ $x[$j + 32] = $x[$j + 16] ^ $x[$j];
+ }
+ $t = chr(0);
+ for ($j = 0; $j < 18; $j++) {
+ for ($k = 0; $k < 48; $k++) {
+ $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
+ //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
+ }
+ $t = chr(ord($t) + $j);
+ }
+ }
+
+ // Step 5. Output
+ return substr($x, 0, 16);
+ }
+
+ /**
+ * Pure-PHP implementation of SHA256
+ *
+ * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
+ *
+ * @access private
+ * @param string $m
+ */
+ function _sha256($m)
+ {
+ if (extension_loaded('suhosin')) {
+ return pack('H*', sha256($m));
+ }
+
+ // Initialize variables
+ $hash = array(
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+ );
+ // Initialize table of round constants
+ // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
+ static $k = array(
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ );
+
+ // Pre-processing
+ $length = strlen($m);
+ // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
+ $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
+ $m[$length] = chr(0x80);
+ // we don't support hashing strings 512MB long
+ $m.= pack('N2', 0, $length << 3);
+
+ // Process the message in successive 512-bit chunks
+ $chunks = str_split($m, 64);
+ foreach ($chunks as $chunk) {
+ $w = array();
+ for ($i = 0; $i < 16; $i++) {
+ extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
+ $w[] = $temp;
+ }
+
+ // Extend the sixteen 32-bit words into sixty-four 32-bit words
+ for ($i = 16; $i < 64; $i++) {
+ // @codingStandardsIgnoreStart
+ $s0 = $this->_rightRotate($w[$i - 15], 7) ^
+ $this->_rightRotate($w[$i - 15], 18) ^
+ $this->_rightShift( $w[$i - 15], 3);
+ $s1 = $this->_rightRotate($w[$i - 2], 17) ^
+ $this->_rightRotate($w[$i - 2], 19) ^
+ $this->_rightShift( $w[$i - 2], 10);
+ // @codingStandardsIgnoreEnd
+ $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
+ }
+
+ // Initialize hash value for this chunk
+ list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
+
+ // Main loop
+ for ($i = 0; $i < 64; $i++) {
+ $s0 = $this->_rightRotate($a, 2) ^
+ $this->_rightRotate($a, 13) ^
+ $this->_rightRotate($a, 22);
+ $maj = ($a & $b) ^
+ ($a & $c) ^
+ ($b & $c);
+ $t2 = $this->_add($s0, $maj);
+
+ $s1 = $this->_rightRotate($e, 6) ^
+ $this->_rightRotate($e, 11) ^
+ $this->_rightRotate($e, 25);
+ $ch = ($e & $f) ^
+ ($this->_not($e) & $g);
+ $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
+
+ $h = $g;
+ $g = $f;
+ $f = $e;
+ $e = $this->_add($d, $t1);
+ $d = $c;
+ $c = $b;
+ $b = $a;
+ $a = $this->_add($t1, $t2);
+ }
+
+ // Add this chunk's hash to result so far
+ $hash = array(
+ $this->_add($hash[0], $a),
+ $this->_add($hash[1], $b),
+ $this->_add($hash[2], $c),
+ $this->_add($hash[3], $d),
+ $this->_add($hash[4], $e),
+ $this->_add($hash[5], $f),
+ $this->_add($hash[6], $g),
+ $this->_add($hash[7], $h)
+ );
+ }
+
+ // Produce the final hash value (big-endian)
+ return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
+ }
+
+ /**
+ * Pure-PHP implementation of SHA384 and SHA512
+ *
+ * @access private
+ * @param string $m
+ */
+ function _sha512($m)
+ {
+ static $init384, $init512, $k;
+
+ if (!isset($k)) {
+ // Initialize variables
+ $init384 = array( // initial values for SHA384
+ 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
+ '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
+ );
+ $init512 = array( // initial values for SHA512
+ '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
+ '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
+ );
+
+ for ($i = 0; $i < 8; $i++) {
+ $init384[$i] = new BigInteger($init384[$i], 16);
+ $init384[$i]->setPrecision(64);
+ $init512[$i] = new BigInteger($init512[$i], 16);
+ $init512[$i]->setPrecision(64);
+ }
+
+ // Initialize table of round constants
+ // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
+ $k = array(
+ '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
+ '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
+ 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
+ '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
+ 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
+ '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
+ '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
+ 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
+ '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
+ '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
+ 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
+ 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
+ '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
+ '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
+ '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
+ '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
+ 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
+ '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
+ '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
+ '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
+ );
+
+ for ($i = 0; $i < 80; $i++) {
+ $k[$i] = new BigInteger($k[$i], 16);
+ }
+ }
+
+ $hash = $this->l == 48 ? $init384 : $init512;
+
+ // Pre-processing
+ $length = strlen($m);
+ // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
+ $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
+ $m[$length] = chr(0x80);
+ // we don't support hashing strings 512MB long
+ $m.= pack('N4', 0, 0, 0, $length << 3);
+
+ // Process the message in successive 1024-bit chunks
+ $chunks = str_split($m, 128);
+ foreach ($chunks as $chunk) {
+ $w = array();
+ for ($i = 0; $i < 16; $i++) {
+ $temp = new BigInteger($this->_string_shift($chunk, 8), 256);
+ $temp->setPrecision(64);
+ $w[] = $temp;
+ }
+
+ // Extend the sixteen 32-bit words into eighty 32-bit words
+ for ($i = 16; $i < 80; $i++) {
+ $temp = array(
+ $w[$i - 15]->bitwise_rightRotate(1),
+ $w[$i - 15]->bitwise_rightRotate(8),
+ $w[$i - 15]->bitwise_rightShift(7)
+ );
+ $s0 = $temp[0]->bitwise_xor($temp[1]);
+ $s0 = $s0->bitwise_xor($temp[2]);
+ $temp = array(
+ $w[$i - 2]->bitwise_rightRotate(19),
+ $w[$i - 2]->bitwise_rightRotate(61),
+ $w[$i - 2]->bitwise_rightShift(6)
+ );
+ $s1 = $temp[0]->bitwise_xor($temp[1]);
+ $s1 = $s1->bitwise_xor($temp[2]);
+ $w[$i] = $w[$i - 16]->copy();
+ $w[$i] = $w[$i]->add($s0);
+ $w[$i] = $w[$i]->add($w[$i - 7]);
+ $w[$i] = $w[$i]->add($s1);
+ }
+
+ // Initialize hash value for this chunk
+ $a = $hash[0]->copy();
+ $b = $hash[1]->copy();
+ $c = $hash[2]->copy();
+ $d = $hash[3]->copy();
+ $e = $hash[4]->copy();
+ $f = $hash[5]->copy();
+ $g = $hash[6]->copy();
+ $h = $hash[7]->copy();
+
+ // Main loop
+ for ($i = 0; $i < 80; $i++) {
+ $temp = array(
+ $a->bitwise_rightRotate(28),
+ $a->bitwise_rightRotate(34),
+ $a->bitwise_rightRotate(39)
+ );
+ $s0 = $temp[0]->bitwise_xor($temp[1]);
+ $s0 = $s0->bitwise_xor($temp[2]);
+ $temp = array(
+ $a->bitwise_and($b),
+ $a->bitwise_and($c),
+ $b->bitwise_and($c)
+ );
+ $maj = $temp[0]->bitwise_xor($temp[1]);
+ $maj = $maj->bitwise_xor($temp[2]);
+ $t2 = $s0->add($maj);
+
+ $temp = array(
+ $e->bitwise_rightRotate(14),
+ $e->bitwise_rightRotate(18),
+ $e->bitwise_rightRotate(41)
+ );
+ $s1 = $temp[0]->bitwise_xor($temp[1]);
+ $s1 = $s1->bitwise_xor($temp[2]);
+ $temp = array(
+ $e->bitwise_and($f),
+ $g->bitwise_and($e->bitwise_not())
+ );
+ $ch = $temp[0]->bitwise_xor($temp[1]);
+ $t1 = $h->add($s1);
+ $t1 = $t1->add($ch);
+ $t1 = $t1->add($k[$i]);
+ $t1 = $t1->add($w[$i]);
+
+ $h = $g->copy();
+ $g = $f->copy();
+ $f = $e->copy();
+ $e = $d->add($t1);
+ $d = $c->copy();
+ $c = $b->copy();
+ $b = $a->copy();
+ $a = $t1->add($t2);
+ }
+
+ // Add this chunk's hash to result so far
+ $hash = array(
+ $hash[0]->add($a),
+ $hash[1]->add($b),
+ $hash[2]->add($c),
+ $hash[3]->add($d),
+ $hash[4]->add($e),
+ $hash[5]->add($f),
+ $hash[6]->add($g),
+ $hash[7]->add($h)
+ );
+ }
+
+ // Produce the final hash value (big-endian)
+ // (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
+ $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
+ $hash[4]->toBytes() . $hash[5]->toBytes();
+ if ($this->l != 48) {
+ $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
+ }
+
+ return $temp;
+ }
+
+ /**
+ * Right Rotate
+ *
+ * @access private
+ * @param int $int
+ * @param int $amt
+ * @see self::_sha256()
+ * @return int
+ */
+ function _rightRotate($int, $amt)
+ {
+ $invamt = 32 - $amt;
+ $mask = (1 << $invamt) - 1;
+ return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
+ }
+
+ /**
+ * Right Shift
+ *
+ * @access private
+ * @param int $int
+ * @param int $amt
+ * @see self::_sha256()
+ * @return int
+ */
+ function _rightShift($int, $amt)
+ {
+ $mask = (1 << (32 - $amt)) - 1;
+ return ($int >> $amt) & $mask;
+ }
+
+ /**
+ * Not
+ *
+ * @access private
+ * @param int $int
+ * @see self::_sha256()
+ * @return int
+ */
+ function _not($int)
+ {
+ return ~$int & 0xFFFFFFFF;
+ }
+
+ /**
+ * Add
+ *
+ * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
+ * possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
+ *
+ * @param int $...
+ * @return int
+ * @see self::_sha256()
+ * @access private
+ */
+ function _add()
+ {
+ static $mod;
+ if (!isset($mod)) {
+ $mod = pow(2, 32);
+ }
+
+ $result = 0;
+ $arguments = func_get_args();
+ foreach ($arguments as $argument) {
+ $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
+ }
+
+ if ((php_uname('m') & "\xDF\xDF\xDF") != 'ARM') {
+ return fmod($result, $mod);
+ }
+
+ return (fmod($result, 0x80000000) & 0x7FFFFFFF) |
+ ((fmod(floor($result / 0x80000000), 2) & 1) << 31);
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @return string
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of RC2.
+ *
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://tools.ietf.org/html/rfc2268}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $rc2 = new \phpseclib\Crypt\RC2();
+ *
+ * $rc2->setKey('abcdefgh');
+ *
+ * $plaintext = str_repeat('a', 1024);
+ *
+ * echo $rc2->decrypt($rc2->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package RC2
+ * @author Patrick Monnerat <pm@datasphere.ch>
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of RC2.
+ *
+ * @package RC2
+ * @access public
+ */
+class RC2 extends Base
+{
+ /**
+ * Block Length of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::block_size
+ * @var int
+ * @access private
+ */
+ var $block_size = 8;
+
+ /**
+ * The Key
+ *
+ * @see \phpseclib\Crypt\Base::key
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $key;
+
+ /**
+ * The Original (unpadded) Key
+ *
+ * @see \phpseclib\Crypt\Base::key
+ * @see self::setKey()
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @var string
+ * @access private
+ */
+ var $orig_key;
+
+ /**
+ * Don't truncate / null pad key
+ *
+ * @see \phpseclib\Crypt\Base::_clearBuffers()
+ * @var bool
+ * @access private
+ */
+ var $skip_key_adjustment = true;
+
+ /**
+ * Key Length (in bytes)
+ *
+ * @see \phpseclib\Crypt\RC2::setKeyLength()
+ * @var int
+ * @access private
+ */
+ var $key_length = 16; // = 128 bits
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'rc2';
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * @see \phpseclib\Crypt\Base::cfb_init_len
+ * @var int
+ * @access private
+ */
+ var $cfb_init_len = 500;
+
+ /**
+ * The key length in bits.
+ *
+ * @see self::setKeyLength()
+ * @see self::setKey()
+ * @var int
+ * @access private
+ * @internal Should be in range [1..1024].
+ * @internal Changing this value after setting the key has no effect.
+ */
+ var $default_key_length = 1024;
+
+ /**
+ * The key length in bits.
+ *
+ * @see self::isValidEnine()
+ * @see self::setKey()
+ * @var int
+ * @access private
+ * @internal Should be in range [1..1024].
+ */
+ var $current_key_length;
+
+ /**
+ * The Key Schedule
+ *
+ * @see self::_setupKey()
+ * @var array
+ * @access private
+ */
+ var $keys;
+
+ /**
+ * Key expansion randomization table.
+ * Twice the same 256-value sequence to save a modulus in key expansion.
+ *
+ * @see self::setKey()
+ * @var array
+ * @access private
+ */
+ var $pitable = array(
+ 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
+ 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
+ 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
+ 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
+ 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
+ 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
+ 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
+ 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
+ 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
+ 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
+ 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
+ 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
+ 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
+ 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
+ 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
+ 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
+ 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
+ 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
+ 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
+ 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
+ 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
+ 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
+ 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
+ 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
+ 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
+ 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
+ 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
+ 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
+ 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
+ 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
+ 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
+ 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
+ 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
+ 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
+ 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
+ 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
+ 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
+ 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
+ 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
+ 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
+ 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
+ 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
+ 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
+ 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
+ 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
+ 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
+ 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
+ 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
+ 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
+ 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
+ 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
+ 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
+ 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
+ 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
+ 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
+ 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
+ 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
+ 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
+ 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
+ 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
+ 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
+ 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
+ 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
+ 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
+ );
+
+ /**
+ * Inverse key expansion randomization table.
+ *
+ * @see self::setKey()
+ * @var array
+ * @access private
+ */
+ var $invpitable = array(
+ 0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
+ 0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
+ 0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
+ 0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
+ 0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
+ 0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
+ 0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
+ 0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
+ 0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
+ 0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
+ 0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
+ 0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
+ 0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
+ 0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
+ 0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
+ 0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
+ 0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
+ 0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
+ 0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
+ 0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
+ 0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
+ 0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
+ 0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
+ 0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
+ 0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
+ 0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
+ 0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
+ 0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
+ 0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
+ 0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
+ 0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
+ 0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
+ );
+
+ /**
+ * Test for engine validity
+ *
+ * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
+ *
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ switch ($engine) {
+ case self::ENGINE_OPENSSL:
+ if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
+ return false;
+ }
+ $this->cipher_name_openssl_ecb = 'rc2-ecb';
+ $this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
+ }
+
+ return parent::isValidEngine($engine);
+ }
+
+ /**
+ * Sets the key length.
+ *
+ * Valid key lengths are 8 to 1024.
+ * Calling this function after setting the key has no effect until the next
+ * \phpseclib\Crypt\RC2::setKey() call.
+ *
+ * @access public
+ * @param int $length in bits
+ */
+ function setKeyLength($length)
+ {
+ if ($length < 8) {
+ $this->default_key_length = 1;
+ } elseif ($length > 1024) {
+ $this->default_key_length = 128;
+ } else {
+ $this->default_key_length = $length;
+ }
+ $this->current_key_length = $this->default_key_length;
+
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Returns the current key length
+ *
+ * @access public
+ * @return int
+ */
+ function getKeyLength()
+ {
+ return $this->current_key_length;
+ }
+
+ /**
+ * Sets the key.
+ *
+ * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
+ * strlen($key) <= 128), however, we only use the first 128 bytes if $key
+ * has more then 128 bytes in it, and set $key to a single null byte if
+ * it is empty.
+ *
+ * If the key is not explicitly set, it'll be assumed to be a single
+ * null byte.
+ *
+ * @see \phpseclib\Crypt\Base::setKey()
+ * @access public
+ * @param string $key
+ * @param int $t1 optional Effective key length in bits.
+ */
+ function setKey($key, $t1 = 0)
+ {
+ $this->orig_key = $key;
+
+ if ($t1 <= 0) {
+ $t1 = $this->default_key_length;
+ } elseif ($t1 > 1024) {
+ $t1 = 1024;
+ }
+ $this->current_key_length = $t1;
+ // Key byte count should be 1..128.
+ $key = strlen($key) ? substr($key, 0, 128) : "\x00";
+ $t = strlen($key);
+
+ // The mcrypt RC2 implementation only supports effective key length
+ // of 1024 bits. It is however possible to handle effective key
+ // lengths in range 1..1024 by expanding the key and applying
+ // inverse pitable mapping to the first byte before submitting it
+ // to mcrypt.
+
+ // Key expansion.
+ $l = array_values(unpack('C*', $key));
+ $t8 = ($t1 + 7) >> 3;
+ $tm = 0xFF >> (8 * $t8 - $t1);
+
+ // Expand key.
+ $pitable = $this->pitable;
+ for ($i = $t; $i < 128; $i++) {
+ $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
+ }
+ $i = 128 - $t8;
+ $l[$i] = $pitable[$l[$i] & $tm];
+ while ($i--) {
+ $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
+ }
+
+ // Prepare the key for mcrypt.
+ $l[0] = $this->invpitable[$l[0]];
+ array_unshift($l, 'C*');
+
+ parent::setKey(call_user_func_array('pack', $l));
+ }
+
+ /**
+ * Encrypts a message.
+ *
+ * Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code
+ *
+ * @see self::decrypt()
+ * @access public
+ * @param string $plaintext
+ * @return string $ciphertext
+ */
+ function encrypt($plaintext)
+ {
+ if ($this->engine == self::ENGINE_OPENSSL) {
+ $temp = $this->key;
+ $this->key = $this->orig_key;
+ $result = parent::encrypt($plaintext);
+ $this->key = $temp;
+ return $result;
+ }
+
+ return parent::encrypt($plaintext);
+ }
+
+ /**
+ * Decrypts a message.
+ *
+ * Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code
+ *
+ * @see self::encrypt()
+ * @access public
+ * @param string $ciphertext
+ * @return string $plaintext
+ */
+ function decrypt($ciphertext)
+ {
+ if ($this->engine == self::ENGINE_OPENSSL) {
+ $temp = $this->key;
+ $this->key = $this->orig_key;
+ $result = parent::decrypt($ciphertext);
+ $this->key = $temp;
+ return $result;
+ }
+
+ return parent::decrypt($ciphertext);
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @see \phpseclib\Crypt\Base::_encryptBlock()
+ * @see \phpseclib\Crypt\Base::encrypt()
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _encryptBlock($in)
+ {
+ list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
+ $keys = $this->keys;
+ $limit = 20;
+ $actions = array($limit => 44, 44 => 64);
+ $j = 0;
+
+ for (;;) {
+ // Mixing round.
+ $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
+ $r0 |= $r0 >> 16;
+ $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
+ $r1 |= $r1 >> 16;
+ $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
+ $r2 |= $r2 >> 16;
+ $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
+ $r3 |= $r3 >> 16;
+
+ if ($j === $limit) {
+ if ($limit === 64) {
+ break;
+ }
+
+ // Mashing round.
+ $r0 += $keys[$r3 & 0x3F];
+ $r1 += $keys[$r0 & 0x3F];
+ $r2 += $keys[$r1 & 0x3F];
+ $r3 += $keys[$r2 & 0x3F];
+ $limit = $actions[$limit];
+ }
+ }
+
+ return pack('vvvv', $r0, $r1, $r2, $r3);
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @see \phpseclib\Crypt\Base::_decryptBlock()
+ * @see \phpseclib\Crypt\Base::decrypt()
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _decryptBlock($in)
+ {
+ list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
+ $keys = $this->keys;
+ $limit = 44;
+ $actions = array($limit => 20, 20 => 0);
+ $j = 64;
+
+ for (;;) {
+ // R-mixing round.
+ $r3 = ($r3 | ($r3 << 16)) >> 5;
+ $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
+ $r2 = ($r2 | ($r2 << 16)) >> 3;
+ $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
+ $r1 = ($r1 | ($r1 << 16)) >> 2;
+ $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
+ $r0 = ($r0 | ($r0 << 16)) >> 1;
+ $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
+
+ if ($j === $limit) {
+ if ($limit === 0) {
+ break;
+ }
+
+ // R-mashing round.
+ $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
+ $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
+ $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
+ $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
+ $limit = $actions[$limit];
+ }
+ }
+
+ return pack('vvvv', $r0, $r1, $r2, $r3);
+ }
+
+ /**
+ * Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
+ *
+ * @see \phpseclib\Crypt\Base::_setupMcrypt()
+ * @access private
+ */
+ function _setupMcrypt()
+ {
+ if (!isset($this->key)) {
+ $this->setKey('');
+ }
+
+ parent::_setupMcrypt();
+ }
+
+ /**
+ * Creates the key schedule
+ *
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ if (!isset($this->key)) {
+ $this->setKey('');
+ }
+
+ // Key has already been expanded in \phpseclib\Crypt\RC2::setKey():
+ // Only the first value must be altered.
+ $l = unpack('Ca/Cb/v*', $this->key);
+ array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
+ unset($l['a']);
+ unset($l['b']);
+ $this->keys = $l;
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ $lambda_functions =& self::_getLambdaFunctions();
+
+ // The first 10 generated $lambda_functions will use the $keys hardcoded as integers
+ // for the mixing rounds, for better inline crypt performance [~20% faster].
+ // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
+ // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
+
+ // Generation of a unique hash for our generated code
+ $code_hash = "Crypt_RC2, {$this->mode}";
+ if ($gen_hi_opt_code) {
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
+ }
+
+ // Is there a re-usable $lambda_functions in there?
+ // If not, we have to create it.
+ if (!isset($lambda_functions[$code_hash])) {
+ // Init code for both, encrypt and decrypt.
+ $init_crypt = '$keys = $self->keys;';
+
+ switch (true) {
+ case $gen_hi_opt_code:
+ $keys = $this->keys;
+ default:
+ $keys = array();
+ foreach ($this->keys as $k => $v) {
+ $keys[$k] = '$keys[' . $k . ']';
+ }
+ }
+
+ // $in is the current 8 bytes block which has to be en/decrypt
+ $encrypt_block = $decrypt_block = '
+ $in = unpack("v4", $in);
+ $r0 = $in[1];
+ $r1 = $in[2];
+ $r2 = $in[3];
+ $r3 = $in[4];
+ ';
+
+ // Create code for encryption.
+ $limit = 20;
+ $actions = array($limit => 44, 44 => 64);
+ $j = 0;
+
+ for (;;) {
+ // Mixing round.
+ $encrypt_block .= '
+ $r0 = (($r0 + ' . $keys[$j++] . ' +
+ ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
+ $r0 |= $r0 >> 16;
+ $r1 = (($r1 + ' . $keys[$j++] . ' +
+ ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
+ $r1 |= $r1 >> 16;
+ $r2 = (($r2 + ' . $keys[$j++] . ' +
+ ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
+ $r2 |= $r2 >> 16;
+ $r3 = (($r3 + ' . $keys[$j++] . ' +
+ ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
+ $r3 |= $r3 >> 16;';
+
+ if ($j === $limit) {
+ if ($limit === 64) {
+ break;
+ }
+
+ // Mashing round.
+ $encrypt_block .= '
+ $r0 += $keys[$r3 & 0x3F];
+ $r1 += $keys[$r0 & 0x3F];
+ $r2 += $keys[$r1 & 0x3F];
+ $r3 += $keys[$r2 & 0x3F];';
+ $limit = $actions[$limit];
+ }
+ }
+
+ $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
+
+ // Create code for decryption.
+ $limit = 44;
+ $actions = array($limit => 20, 20 => 0);
+ $j = 64;
+
+ for (;;) {
+ // R-mixing round.
+ $decrypt_block .= '
+ $r3 = ($r3 | ($r3 << 16)) >> 5;
+ $r3 = ($r3 - ' . $keys[--$j] . ' -
+ ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
+ $r2 = ($r2 | ($r2 << 16)) >> 3;
+ $r2 = ($r2 - ' . $keys[--$j] . ' -
+ ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
+ $r1 = ($r1 | ($r1 << 16)) >> 2;
+ $r1 = ($r1 - ' . $keys[--$j] . ' -
+ ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
+ $r0 = ($r0 | ($r0 << 16)) >> 1;
+ $r0 = ($r0 - ' . $keys[--$j] . ' -
+ ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
+
+ if ($j === $limit) {
+ if ($limit === 0) {
+ break;
+ }
+
+ // R-mashing round.
+ $decrypt_block .= '
+ $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
+ $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
+ $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
+ $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
+ $limit = $actions[$limit];
+ }
+ }
+
+ $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
+
+ // Creates the inline-crypt function
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
+ array(
+ 'init_crypt' => $init_crypt,
+ 'encrypt_block' => $encrypt_block,
+ 'decrypt_block' => $decrypt_block
+ )
+ );
+ }
+
+ // Set the inline-crypt function as callback in: $this->inline_crypt
+ $this->inline_crypt = $lambda_functions[$code_hash];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of RC4.
+ *
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
+ * - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
+ *
+ * RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
+ * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $rc4 = new \phpseclib\Crypt\RC4();
+ *
+ * $rc4->setKey('abcdefgh');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $rc4->decrypt($rc4->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package RC4
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of RC4.
+ *
+ * @package RC4
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class RC4 extends Base
+{
+ /**#@+
+ * @access private
+ * @see \phpseclib\Crypt\RC4::_crypt()
+ */
+ const ENCRYPT = 0;
+ const DECRYPT = 1;
+ /**#@-*/
+
+ /**
+ * Block Length of the cipher
+ *
+ * RC4 is a stream cipher
+ * so we the block_size to 0
+ *
+ * @see \phpseclib\Crypt\Base::block_size
+ * @var int
+ * @access private
+ */
+ var $block_size = 0;
+
+ /**
+ * Key Length (in bytes)
+ *
+ * @see \phpseclib\Crypt\RC4::setKeyLength()
+ * @var int
+ * @access private
+ */
+ var $key_length = 128; // = 1024 bits
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'arcfour';
+
+ /**
+ * Holds whether performance-optimized $inline_crypt() can/should be used.
+ *
+ * @see \phpseclib\Crypt\Base::inline_crypt
+ * @var mixed
+ * @access private
+ */
+ var $use_inline_crypt = false; // currently not available
+
+ /**
+ * The Key
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ var $key;
+
+ /**
+ * The Key Stream for decryption and encryption
+ *
+ * @see self::setKey()
+ * @var array
+ * @access private
+ */
+ var $stream;
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @return \phpseclib\Crypt\RC4
+ * @access public
+ */
+ function __construct()
+ {
+ parent::__construct(Base::MODE_STREAM);
+ }
+
+ /**
+ * Test for engine validity
+ *
+ * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
+ *
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ if ($engine == Base::ENGINE_OPENSSL) {
+ if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
+ $this->cipher_name_openssl = 'rc4-40';
+ } else {
+ switch (strlen($this->key)) {
+ case 5:
+ $this->cipher_name_openssl = 'rc4-40';
+ break;
+ case 8:
+ $this->cipher_name_openssl = 'rc4-64';
+ break;
+ case 16:
+ $this->cipher_name_openssl = 'rc4';
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+
+ return parent::isValidEngine($engine);
+ }
+
+ /**
+ * Dummy function.
+ *
+ * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
+ * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
+ * calling setKey().
+ *
+ * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
+ * the IV's are relatively easy to predict, an attack described by
+ * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
+ * can be used to quickly guess at the rest of the key. The following links elaborate:
+ *
+ * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
+ * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
+ *
+ * @param string $iv
+ * @see self::setKey()
+ * @access public
+ */
+ function setIV($iv)
+ {
+ }
+
+ /**
+ * Sets the key length
+ *
+ * Keys can be between 1 and 256 bytes long.
+ *
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ if ($length < 8) {
+ $this->key_length = 1;
+ } elseif ($length > 2048) {
+ $this->key_length = 256;
+ } else {
+ $this->key_length = $length >> 3;
+ }
+
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Encrypts a message.
+ *
+ * @see \phpseclib\Crypt\Base::decrypt()
+ * @see self::_crypt()
+ * @access public
+ * @param string $plaintext
+ * @return string $ciphertext
+ */
+ function encrypt($plaintext)
+ {
+ if ($this->engine != Base::ENGINE_INTERNAL) {
+ return parent::encrypt($plaintext);
+ }
+ return $this->_crypt($plaintext, self::ENCRYPT);
+ }
+
+ /**
+ * Decrypts a message.
+ *
+ * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
+ * At least if the continuous buffer is disabled.
+ *
+ * @see \phpseclib\Crypt\Base::encrypt()
+ * @see self::_crypt()
+ * @access public
+ * @param string $ciphertext
+ * @return string $plaintext
+ */
+ function decrypt($ciphertext)
+ {
+ if ($this->engine != Base::ENGINE_INTERNAL) {
+ return parent::decrypt($ciphertext);
+ }
+ return $this->_crypt($ciphertext, self::DECRYPT);
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @access private
+ * @param string $in
+ */
+ function _encryptBlock($in)
+ {
+ // RC4 does not utilize this method
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @access private
+ * @param string $in
+ */
+ function _decryptBlock($in)
+ {
+ // RC4 does not utilize this method
+ }
+
+ /**
+ * Setup the key (expansion)
+ *
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ $key = $this->key;
+ $keyLength = strlen($key);
+ $keyStream = range(0, 255);
+ $j = 0;
+ for ($i = 0; $i < 256; $i++) {
+ $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
+ $temp = $keyStream[$i];
+ $keyStream[$i] = $keyStream[$j];
+ $keyStream[$j] = $temp;
+ }
+
+ $this->stream = array();
+ $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = array(
+ 0, // index $i
+ 0, // index $j
+ $keyStream
+ );
+ }
+
+ /**
+ * Encrypts or decrypts a message.
+ *
+ * @see self::encrypt()
+ * @see self::decrypt()
+ * @access private
+ * @param string $text
+ * @param int $mode
+ * @return string $text
+ */
+ function _crypt($text, $mode)
+ {
+ if ($this->changed) {
+ $this->_setup();
+ $this->changed = false;
+ }
+
+ $stream = &$this->stream[$mode];
+ if ($this->continuousBuffer) {
+ $i = &$stream[0];
+ $j = &$stream[1];
+ $keyStream = &$stream[2];
+ } else {
+ $i = $stream[0];
+ $j = $stream[1];
+ $keyStream = $stream[2];
+ }
+
+ $len = strlen($text);
+ for ($k = 0; $k < $len; ++$k) {
+ $i = ($i + 1) & 255;
+ $ksi = $keyStream[$i];
+ $j = ($j + $ksi) & 255;
+ $ksj = $keyStream[$j];
+
+ $keyStream[$i] = $ksj;
+ $keyStream[$j] = $ksi;
+ $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
+ }
+
+ return $text;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
+ *
+ * PHP version 5
+ *
+ * Here's an example of how to encrypt and decrypt text with this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $rsa = new \phpseclib\Crypt\RSA();
+ * extract($rsa->createKey());
+ *
+ * $plaintext = 'terrafrost';
+ *
+ * $rsa->loadKey($privatekey);
+ * $ciphertext = $rsa->encrypt($plaintext);
+ *
+ * $rsa->loadKey($publickey);
+ * echo $rsa->decrypt($ciphertext);
+ * ?>
+ * </code>
+ *
+ * Here's an example of how to create signatures and verify signatures with this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $rsa = new \phpseclib\Crypt\RSA();
+ * extract($rsa->createKey());
+ *
+ * $plaintext = 'terrafrost';
+ *
+ * $rsa->loadKey($privatekey);
+ * $signature = $rsa->sign($plaintext);
+ *
+ * $rsa->loadKey($publickey);
+ * echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package RSA
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2009 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+use phpseclib\Math\BigInteger;
+
+/**
+ * Pure-PHP PKCS#1 compliant implementation of RSA.
+ *
+ * @package RSA
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class RSA
+{
+ /**#@+
+ * @access public
+ * @see self::encrypt()
+ * @see self::decrypt()
+ */
+ /**
+ * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
+ * (OAEP) for encryption / decryption.
+ *
+ * Uses sha1 by default.
+ *
+ * @see self::setHash()
+ * @see self::setMGFHash()
+ */
+ const ENCRYPTION_OAEP = 1;
+ /**
+ * Use PKCS#1 padding.
+ *
+ * Although self::ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards
+ * compatibility with protocols (like SSH-1) written before OAEP's introduction.
+ */
+ const ENCRYPTION_PKCS1 = 2;
+ /**
+ * Do not use any padding
+ *
+ * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
+ * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
+ */
+ const ENCRYPTION_NONE = 3;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see self::sign()
+ * @see self::verify()
+ * @see self::setHash()
+ */
+ /**
+ * Use the Probabilistic Signature Scheme for signing
+ *
+ * Uses sha1 by default.
+ *
+ * @see self::setSaltLength()
+ * @see self::setMGFHash()
+ */
+ const SIGNATURE_PSS = 1;
+ /**
+ * Use the PKCS#1 scheme by default.
+ *
+ * Although self::SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards
+ * compatibility with protocols (like SSH-2) written before PSS's introduction.
+ */
+ const SIGNATURE_PKCS1 = 2;
+ /**#@-*/
+
+ /**#@+
+ * @access private
+ * @see \phpseclib\Crypt\RSA::createKey()
+ */
+ /**
+ * ASN1 Integer
+ */
+ const ASN1_INTEGER = 2;
+ /**
+ * ASN1 Bit String
+ */
+ const ASN1_BITSTRING = 3;
+ /**
+ * ASN1 Octet String
+ */
+ const ASN1_OCTETSTRING = 4;
+ /**
+ * ASN1 Object Identifier
+ */
+ const ASN1_OBJECT = 6;
+ /**
+ * ASN1 Sequence (with the constucted bit set)
+ */
+ const ASN1_SEQUENCE = 48;
+ /**#@-*/
+
+ /**#@+
+ * @access private
+ * @see \phpseclib\Crypt\RSA::__construct()
+ */
+ /**
+ * To use the pure-PHP implementation
+ */
+ const MODE_INTERNAL = 1;
+ /**
+ * To use the OpenSSL library
+ *
+ * (if enabled; otherwise, the internal implementation will be used)
+ */
+ const MODE_OPENSSL = 2;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Crypt\RSA::createKey()
+ * @see \phpseclib\Crypt\RSA::setPrivateKeyFormat()
+ */
+ /**
+ * PKCS#1 formatted private key
+ *
+ * Used by OpenSSH
+ */
+ const PRIVATE_FORMAT_PKCS1 = 0;
+ /**
+ * PuTTY formatted private key
+ */
+ const PRIVATE_FORMAT_PUTTY = 1;
+ /**
+ * XML formatted private key
+ */
+ const PRIVATE_FORMAT_XML = 2;
+ /**
+ * PKCS#8 formatted private key
+ */
+ const PRIVATE_FORMAT_PKCS8 = 8;
+ /**
+ * OpenSSH formatted private key
+ */
+ const PRIVATE_FORMAT_OPENSSH = 9;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Crypt\RSA::createKey()
+ * @see \phpseclib\Crypt\RSA::setPublicKeyFormat()
+ */
+ /**
+ * Raw public key
+ *
+ * An array containing two \phpseclib\Math\BigInteger objects.
+ *
+ * The exponent can be indexed with any of the following:
+ *
+ * 0, e, exponent, publicExponent
+ *
+ * The modulus can be indexed with any of the following:
+ *
+ * 1, n, modulo, modulus
+ */
+ const PUBLIC_FORMAT_RAW = 3;
+ /**
+ * PKCS#1 formatted public key (raw)
+ *
+ * Used by File/X509.php
+ *
+ * Has the following header:
+ *
+ * -----BEGIN RSA PUBLIC KEY-----
+ *
+ * Analogous to ssh-keygen's pem format (as specified by -m)
+ */
+ const PUBLIC_FORMAT_PKCS1 = 4;
+ const PUBLIC_FORMAT_PKCS1_RAW = 4;
+ /**
+ * XML formatted public key
+ */
+ const PUBLIC_FORMAT_XML = 5;
+ /**
+ * OpenSSH formatted public key
+ *
+ * Place in $HOME/.ssh/authorized_keys
+ */
+ const PUBLIC_FORMAT_OPENSSH = 6;
+ /**
+ * PKCS#1 formatted public key (encapsulated)
+ *
+ * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
+ *
+ * Has the following header:
+ *
+ * -----BEGIN PUBLIC KEY-----
+ *
+ * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
+ * is specific to private keys it's basically creating a DER-encoded wrapper
+ * for keys. This just extends that same concept to public keys (much like ssh-keygen)
+ */
+ const PUBLIC_FORMAT_PKCS8 = 7;
+ /**#@-*/
+
+ /**
+ * Precomputed Zero
+ *
+ * @var \phpseclib\Math\BigInteger
+ * @access private
+ */
+ var $zero;
+
+ /**
+ * Precomputed One
+ *
+ * @var \phpseclib\Math\BigInteger
+ * @access private
+ */
+ var $one;
+
+ /**
+ * Private Key Format
+ *
+ * @var int
+ * @access private
+ */
+ var $privateKeyFormat = self::PRIVATE_FORMAT_PKCS1;
+
+ /**
+ * Public Key Format
+ *
+ * @var int
+ * @access public
+ */
+ var $publicKeyFormat = self::PUBLIC_FORMAT_PKCS8;
+
+ /**
+ * Modulus (ie. n)
+ *
+ * @var \phpseclib\Math\BigInteger
+ * @access private
+ */
+ var $modulus;
+
+ /**
+ * Modulus length
+ *
+ * @var \phpseclib\Math\BigInteger
+ * @access private
+ */
+ var $k;
+
+ /**
+ * Exponent (ie. e or d)
+ *
+ * @var \phpseclib\Math\BigInteger
+ * @access private
+ */
+ var $exponent;
+
+ /**
+ * Primes for Chinese Remainder Theorem (ie. p and q)
+ *
+ * @var array
+ * @access private
+ */
+ var $primes;
+
+ /**
+ * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
+ *
+ * @var array
+ * @access private
+ */
+ var $exponents;
+
+ /**
+ * Coefficients for Chinese Remainder Theorem (ie. qInv)
+ *
+ * @var array
+ * @access private
+ */
+ var $coefficients;
+
+ /**
+ * Hash name
+ *
+ * @var string
+ * @access private
+ */
+ var $hashName;
+
+ /**
+ * Hash function
+ *
+ * @var \phpseclib\Crypt\Hash
+ * @access private
+ */
+ var $hash;
+
+ /**
+ * Length of hash function output
+ *
+ * @var int
+ * @access private
+ */
+ var $hLen;
+
+ /**
+ * Length of salt
+ *
+ * @var int
+ * @access private
+ */
+ var $sLen;
+
+ /**
+ * Hash function for the Mask Generation Function
+ *
+ * @var \phpseclib\Crypt\Hash
+ * @access private
+ */
+ var $mgfHash;
+
+ /**
+ * Length of MGF hash function output
+ *
+ * @var int
+ * @access private
+ */
+ var $mgfHLen;
+
+ /**
+ * Encryption mode
+ *
+ * @var int
+ * @access private
+ */
+ var $encryptionMode = self::ENCRYPTION_OAEP;
+
+ /**
+ * Signature mode
+ *
+ * @var int
+ * @access private
+ */
+ var $signatureMode = self::SIGNATURE_PSS;
+
+ /**
+ * Public Exponent
+ *
+ * @var mixed
+ * @access private
+ */
+ var $publicExponent = false;
+
+ /**
+ * Password
+ *
+ * @var string
+ * @access private
+ */
+ var $password = false;
+
+ /**
+ * Components
+ *
+ * For use with parsing XML formatted keys. PHP's XML Parser functions use utilized - instead of PHP's DOM functions -
+ * because PHP's XML Parser functions work on PHP4 whereas PHP's DOM functions - although surperior - don't.
+ *
+ * @see self::_start_element_handler()
+ * @var array
+ * @access private
+ */
+ var $components = array();
+
+ /**
+ * Current String
+ *
+ * For use with parsing XML formatted keys.
+ *
+ * @see self::_character_handler()
+ * @see self::_stop_element_handler()
+ * @var mixed
+ * @access private
+ */
+ var $current;
+
+ /**
+ * OpenSSL configuration file name.
+ *
+ * Set to null to use system configuration file.
+ * @see self::createKey()
+ * @var mixed
+ * @Access public
+ */
+ var $configFile;
+
+ /**
+ * Public key comment field.
+ *
+ * @var string
+ * @access private
+ */
+ var $comment = 'phpseclib-generated-key';
+
+ /**
+ * The constructor
+ *
+ * If you want to make use of the openssl extension, you'll need to set the mode manually, yourself. The reason
+ * \phpseclib\Crypt\RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires
+ * openssl.cnf be present somewhere and, unfortunately, the only real way to find out is too late.
+ *
+ * @return \phpseclib\Crypt\RSA
+ * @access public
+ */
+ function __construct()
+ {
+ $this->configFile = dirname(__FILE__) . '/../openssl.cnf';
+
+ if (!defined('CRYPT_RSA_MODE')) {
+ switch (true) {
+ // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
+ // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
+ // can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
+ case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
+ define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
+ break;
+ case extension_loaded('openssl') && file_exists($this->configFile):
+ // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
+ $versions = array();
+
+ // avoid generating errors (even with suppression) when phpinfo() is disabled (common in production systems)
+ if (strpos(ini_get('disable_functions'), 'phpinfo') === false) {
+ ob_start();
+ @phpinfo();
+ $content = ob_get_contents();
+ ob_end_clean();
+
+ preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
+
+ if (!empty($matches[1])) {
+ for ($i = 0; $i < count($matches[1]); $i++) {
+ $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
+
+ // Remove letter part in OpenSSL version
+ if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
+ $versions[$matches[1][$i]] = $fullVersion;
+ } else {
+ $versions[$matches[1][$i]] = $m[0];
+ }
+ }
+ }
+ }
+
+ // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
+ switch (true) {
+ case !isset($versions['Header']):
+ case !isset($versions['Library']):
+ case $versions['Header'] == $versions['Library']:
+ case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
+ define('CRYPT_RSA_MODE', self::MODE_OPENSSL);
+ break;
+ default:
+ define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
+ define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
+ }
+ break;
+ default:
+ define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
+ }
+ }
+
+ $this->zero = new BigInteger();
+ $this->one = new BigInteger(1);
+
+ $this->hash = new Hash('sha1');
+ $this->hLen = $this->hash->getLength();
+ $this->hashName = 'sha1';
+ $this->mgfHash = new Hash('sha1');
+ $this->mgfHLen = $this->mgfHash->getLength();
+ }
+
+ /**
+ * Create public / private key pair
+ *
+ * Returns an array with the following three elements:
+ * - 'privatekey': The private key.
+ * - 'publickey': The public key.
+ * - 'partialkey': A partially computed key (if the execution time exceeded $timeout).
+ * Will need to be passed back to \phpseclib\Crypt\RSA::createKey() as the third parameter for further processing.
+ *
+ * @access public
+ * @param int $bits
+ * @param int $timeout
+ * @param array $p
+ */
+ function createKey($bits = 1024, $timeout = false, $partial = array())
+ {
+ if (!defined('CRYPT_RSA_EXPONENT')) {
+ // http://en.wikipedia.org/wiki/65537_%28number%29
+ define('CRYPT_RSA_EXPONENT', '65537');
+ }
+ // per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
+ // than 256 bits. as a consequence if the key you're trying to create is 1024 bits and you've set CRYPT_RSA_SMALLEST_PRIME
+ // to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). at least if
+ // CRYPT_RSA_MODE is set to self::MODE_INTERNAL. if CRYPT_RSA_MODE is set to self::MODE_OPENSSL then
+ // CRYPT_RSA_SMALLEST_PRIME is ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key
+ // generation when there's a chance neither gmp nor OpenSSL are installed)
+ if (!defined('CRYPT_RSA_SMALLEST_PRIME')) {
+ define('CRYPT_RSA_SMALLEST_PRIME', 4096);
+ }
+
+ // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
+ if (CRYPT_RSA_MODE == self::MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
+ $config = array();
+ if (isset($this->configFile)) {
+ $config['config'] = $this->configFile;
+ }
+ $rsa = openssl_pkey_new(array('private_key_bits' => $bits) + $config);
+ openssl_pkey_export($rsa, $privatekey, null, $config);
+ $publickey = openssl_pkey_get_details($rsa);
+ $publickey = $publickey['key'];
+
+ $privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, self::PRIVATE_FORMAT_PKCS1)));
+ $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, self::PUBLIC_FORMAT_PKCS1)));
+
+ // clear the buffer of error strings stemming from a minimalistic openssl.cnf
+ while (openssl_error_string() !== false) {
+ }
+
+ return array(
+ 'privatekey' => $privatekey,
+ 'publickey' => $publickey,
+ 'partialkey' => false
+ );
+ }
+
+ static $e;
+ if (!isset($e)) {
+ $e = new BigInteger(CRYPT_RSA_EXPONENT);
+ }
+
+ extract($this->_generateMinMax($bits));
+ $absoluteMin = $min;
+ $temp = $bits >> 1; // divide by two to see how many bits P and Q would be
+ if ($temp > CRYPT_RSA_SMALLEST_PRIME) {
+ $num_primes = floor($bits / CRYPT_RSA_SMALLEST_PRIME);
+ $temp = CRYPT_RSA_SMALLEST_PRIME;
+ } else {
+ $num_primes = 2;
+ }
+ extract($this->_generateMinMax($temp + $bits % $temp));
+ $finalMax = $max;
+ extract($this->_generateMinMax($temp));
+
+ $generator = new BigInteger();
+
+ $n = $this->one->copy();
+ if (!empty($partial)) {
+ extract(unserialize($partial));
+ } else {
+ $exponents = $coefficients = $primes = array();
+ $lcm = array(
+ 'top' => $this->one->copy(),
+ 'bottom' => false
+ );
+ }
+
+ $start = time();
+ $i0 = count($primes) + 1;
+
+ do {
+ for ($i = $i0; $i <= $num_primes; $i++) {
+ if ($timeout !== false) {
+ $timeout-= time() - $start;
+ $start = time();
+ if ($timeout <= 0) {
+ return array(
+ 'privatekey' => '',
+ 'publickey' => '',
+ 'partialkey' => serialize(array(
+ 'primes' => $primes,
+ 'coefficients' => $coefficients,
+ 'lcm' => $lcm,
+ 'exponents' => $exponents
+ ))
+ );
+ }
+ }
+
+ if ($i == $num_primes) {
+ list($min, $temp) = $absoluteMin->divide($n);
+ if (!$temp->equals($this->zero)) {
+ $min = $min->add($this->one); // ie. ceil()
+ }
+ $primes[$i] = $generator->randomPrime($min, $finalMax, $timeout);
+ } else {
+ $primes[$i] = $generator->randomPrime($min, $max, $timeout);
+ }
+
+ if ($primes[$i] === false) { // if we've reached the timeout
+ if (count($primes) > 1) {
+ $partialkey = '';
+ } else {
+ array_pop($primes);
+ $partialkey = serialize(array(
+ 'primes' => $primes,
+ 'coefficients' => $coefficients,
+ 'lcm' => $lcm,
+ 'exponents' => $exponents
+ ));
+ }
+
+ return array(
+ 'privatekey' => '',
+ 'publickey' => '',
+ 'partialkey' => $partialkey
+ );
+ }
+
+ // the first coefficient is calculated differently from the rest
+ // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
+ if ($i > 2) {
+ $coefficients[$i] = $n->modInverse($primes[$i]);
+ }
+
+ $n = $n->multiply($primes[$i]);
+
+ $temp = $primes[$i]->subtract($this->one);
+
+ // textbook RSA implementations use Euler's totient function instead of the least common multiple.
+ // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
+ $lcm['top'] = $lcm['top']->multiply($temp);
+ $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
+
+ $exponents[$i] = $e->modInverse($temp);
+ }
+
+ list($temp) = $lcm['top']->divide($lcm['bottom']);
+ $gcd = $temp->gcd($e);
+ $i0 = 1;
+ } while (!$gcd->equals($this->one));
+
+ $d = $e->modInverse($temp);
+
+ $coefficients[2] = $primes[2]->modInverse($primes[1]);
+
+ // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
+ // RSAPrivateKey ::= SEQUENCE {
+ // version Version,
+ // modulus INTEGER, -- n
+ // publicExponent INTEGER, -- e
+ // privateExponent INTEGER, -- d
+ // prime1 INTEGER, -- p
+ // prime2 INTEGER, -- q
+ // exponent1 INTEGER, -- d mod (p-1)
+ // exponent2 INTEGER, -- d mod (q-1)
+ // coefficient INTEGER, -- (inverse of q) mod p
+ // otherPrimeInfos OtherPrimeInfos OPTIONAL
+ // }
+
+ return array(
+ 'privatekey' => $this->_convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients),
+ 'publickey' => $this->_convertPublicKey($n, $e),
+ 'partialkey' => false
+ );
+ }
+
+ /**
+ * Convert a private key to the appropriate format.
+ *
+ * @access private
+ * @see self::setPrivateKeyFormat()
+ * @param string $RSAPrivateKey
+ * @return string
+ */
+ function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
+ {
+ $signed = $this->privateKeyFormat != self::PRIVATE_FORMAT_XML;
+ $num_primes = count($primes);
+ $raw = array(
+ 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
+ 'modulus' => $n->toBytes($signed),
+ 'publicExponent' => $e->toBytes($signed),
+ 'privateExponent' => $d->toBytes($signed),
+ 'prime1' => $primes[1]->toBytes($signed),
+ 'prime2' => $primes[2]->toBytes($signed),
+ 'exponent1' => $exponents[1]->toBytes($signed),
+ 'exponent2' => $exponents[2]->toBytes($signed),
+ 'coefficient' => $coefficients[2]->toBytes($signed)
+ );
+
+ // if the format in question does not support multi-prime rsa and multi-prime rsa was used,
+ // call _convertPublicKey() instead.
+ switch ($this->privateKeyFormat) {
+ case self::PRIVATE_FORMAT_XML:
+ if ($num_primes != 2) {
+ return false;
+ }
+ return "<RSAKeyValue>\r\n" .
+ ' <Modulus>' . base64_encode($raw['modulus']) . "</Modulus>\r\n" .
+ ' <Exponent>' . base64_encode($raw['publicExponent']) . "</Exponent>\r\n" .
+ ' <P>' . base64_encode($raw['prime1']) . "</P>\r\n" .
+ ' <Q>' . base64_encode($raw['prime2']) . "</Q>\r\n" .
+ ' <DP>' . base64_encode($raw['exponent1']) . "</DP>\r\n" .
+ ' <DQ>' . base64_encode($raw['exponent2']) . "</DQ>\r\n" .
+ ' <InverseQ>' . base64_encode($raw['coefficient']) . "</InverseQ>\r\n" .
+ ' <D>' . base64_encode($raw['privateExponent']) . "</D>\r\n" .
+ '</RSAKeyValue>';
+ break;
+ case self::PRIVATE_FORMAT_PUTTY:
+ if ($num_primes != 2) {
+ return false;
+ }
+ $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: ";
+ $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
+ $key.= $encryption;
+ $key.= "\r\nComment: " . $this->comment . "\r\n";
+ $public = pack(
+ 'Na*Na*Na*',
+ strlen('ssh-rsa'),
+ 'ssh-rsa',
+ strlen($raw['publicExponent']),
+ $raw['publicExponent'],
+ strlen($raw['modulus']),
+ $raw['modulus']
+ );
+ $source = pack(
+ 'Na*Na*Na*Na*',
+ strlen('ssh-rsa'),
+ 'ssh-rsa',
+ strlen($encryption),
+ $encryption,
+ strlen($this->comment),
+ $this->comment,
+ strlen($public),
+ $public
+ );
+ $public = base64_encode($public);
+ $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
+ $key.= chunk_split($public, 64);
+ $private = pack(
+ 'Na*Na*Na*Na*',
+ strlen($raw['privateExponent']),
+ $raw['privateExponent'],
+ strlen($raw['prime1']),
+ $raw['prime1'],
+ strlen($raw['prime2']),
+ $raw['prime2'],
+ strlen($raw['coefficient']),
+ $raw['coefficient']
+ );
+ if (empty($this->password) && !is_string($this->password)) {
+ $source.= pack('Na*', strlen($private), $private);
+ $hashkey = 'putty-private-key-file-mac-key';
+ } else {
+ $private.= Random::string(16 - (strlen($private) & 15));
+ $source.= pack('Na*', strlen($private), $private);
+ $sequence = 0;
+ $symkey = '';
+ while (strlen($symkey) < 32) {
+ $temp = pack('Na*', $sequence++, $this->password);
+ $symkey.= pack('H*', sha1($temp));
+ }
+ $symkey = substr($symkey, 0, 32);
+ $crypto = new AES();
+
+ $crypto->setKey($symkey);
+ $crypto->disablePadding();
+ $private = $crypto->encrypt($private);
+ $hashkey = 'putty-private-key-file-mac-key' . $this->password;
+ }
+
+ $private = base64_encode($private);
+ $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
+ $key.= chunk_split($private, 64);
+ $hash = new Hash('sha1');
+ $hash->setKey(pack('H*', sha1($hashkey)));
+ $key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n";
+
+ return $key;
+ case self::PRIVATE_FORMAT_OPENSSH:
+ if ($num_primes != 2) {
+ return false;
+ }
+ $publicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus']);
+ $privateKey = pack(
+ 'Na*Na*Na*Na*Na*Na*Na*',
+ strlen('ssh-rsa'),
+ 'ssh-rsa',
+ strlen($raw['modulus']),
+ $raw['modulus'],
+ strlen($raw['publicExponent']),
+ $raw['publicExponent'],
+ strlen($raw['privateExponent']),
+ $raw['privateExponent'],
+ strlen($raw['coefficient']),
+ $raw['coefficient'],
+ strlen($raw['prime1']),
+ $raw['prime1'],
+ strlen($raw['prime2']),
+ $raw['prime2']
+ );
+ $checkint = Random::string(4);
+ $paddedKey = pack(
+ 'a*Na*',
+ $checkint . $checkint . $privateKey,
+ strlen($this->comment),
+ $this->comment
+ );
+ $paddingLength = (7 * strlen($paddedKey)) % 8;
+ for ($i = 1; $i <= $paddingLength; $i++) {
+ $paddedKey.= chr($i);
+ }
+ $key = pack(
+ 'Na*Na*Na*NNa*Na*',
+ strlen('none'),
+ 'none',
+ strlen('none'),
+ 'none',
+ 0,
+ '',
+ 1,
+ strlen($publicKey),
+ $publicKey,
+ strlen($paddedKey),
+ $paddedKey
+ );
+ $key = "openssh-key-v1\0$key";
+
+ return "-----BEGIN OPENSSH PRIVATE KEY-----\r\n" .
+ chunk_split(base64_encode($key), 70) .
+ "-----END OPENSSH PRIVATE KEY-----";
+ default: // eg. self::PRIVATE_FORMAT_PKCS1
+ $components = array();
+ foreach ($raw as $name => $value) {
+ $components[$name] = pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value);
+ }
+
+ $RSAPrivateKey = implode('', $components);
+
+ if ($num_primes > 2) {
+ $OtherPrimeInfos = '';
+ for ($i = 3; $i <= $num_primes; $i++) {
+ // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
+ //
+ // OtherPrimeInfo ::= SEQUENCE {
+ // prime INTEGER, -- ri
+ // exponent INTEGER, -- di
+ // coefficient INTEGER -- ti
+ // }
+ $OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
+ $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
+ $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
+ $OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
+ }
+ $RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
+ }
+
+ $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
+
+ if ($this->privateKeyFormat == self::PRIVATE_FORMAT_PKCS8) {
+ $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
+ $RSAPrivateKey = pack(
+ 'Ca*a*Ca*a*',
+ self::ASN1_INTEGER,
+ "\01\00",
+ $rsaOID,
+ 4,
+ $this->_encodeLength(strlen($RSAPrivateKey)),
+ $RSAPrivateKey
+ );
+ $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
+ if (!empty($this->password) || is_string($this->password)) {
+ $salt = Random::string(8);
+ $iterationCount = 2048;
+
+ $crypto = new DES();
+ $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
+ $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
+
+ $parameters = pack(
+ 'Ca*a*Ca*N',
+ self::ASN1_OCTETSTRING,
+ $this->_encodeLength(strlen($salt)),
+ $salt,
+ self::ASN1_INTEGER,
+ $this->_encodeLength(4),
+ $iterationCount
+ );
+ $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
+
+ $encryptionAlgorithm = pack(
+ 'Ca*a*Ca*a*',
+ self::ASN1_OBJECT,
+ $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
+ $pbeWithMD5AndDES_CBC,
+ self::ASN1_SEQUENCE,
+ $this->_encodeLength(strlen($parameters)),
+ $parameters
+ );
+
+ $RSAPrivateKey = pack(
+ 'Ca*a*Ca*a*',
+ self::ASN1_SEQUENCE,
+ $this->_encodeLength(strlen($encryptionAlgorithm)),
+ $encryptionAlgorithm,
+ self::ASN1_OCTETSTRING,
+ $this->_encodeLength(strlen($RSAPrivateKey)),
+ $RSAPrivateKey
+ );
+
+ $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
+
+ $RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" .
+ chunk_split(base64_encode($RSAPrivateKey), 64) .
+ '-----END ENCRYPTED PRIVATE KEY-----';
+ } else {
+ $RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" .
+ chunk_split(base64_encode($RSAPrivateKey), 64) .
+ '-----END PRIVATE KEY-----';
+ }
+ return $RSAPrivateKey;
+ }
+
+ if (!empty($this->password) || is_string($this->password)) {
+ $iv = Random::string(8);
+ $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
+ $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
+ $des = new TripleDES();
+ $des->setKey($symkey);
+ $des->setIV($iv);
+ $iv = strtoupper(bin2hex($iv));
+ $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
+ "Proc-Type: 4,ENCRYPTED\r\n" .
+ "DEK-Info: DES-EDE3-CBC,$iv\r\n" .
+ "\r\n" .
+ chunk_split(base64_encode($des->encrypt($RSAPrivateKey)), 64) .
+ '-----END RSA PRIVATE KEY-----';
+ } else {
+ $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
+ chunk_split(base64_encode($RSAPrivateKey), 64) .
+ '-----END RSA PRIVATE KEY-----';
+ }
+
+ return $RSAPrivateKey;
+ }
+ }
+
+ /**
+ * Convert a public key to the appropriate format
+ *
+ * @access private
+ * @see self::setPublicKeyFormat()
+ * @param string $RSAPrivateKey
+ * @return string
+ */
+ function _convertPublicKey($n, $e)
+ {
+ $signed = $this->publicKeyFormat != self::PUBLIC_FORMAT_XML;
+
+ $modulus = $n->toBytes($signed);
+ $publicExponent = $e->toBytes($signed);
+
+ switch ($this->publicKeyFormat) {
+ case self::PUBLIC_FORMAT_RAW:
+ return array('e' => $e->copy(), 'n' => $n->copy());
+ case self::PUBLIC_FORMAT_XML:
+ return "<RSAKeyValue>\r\n" .
+ ' <Modulus>' . base64_encode($modulus) . "</Modulus>\r\n" .
+ ' <Exponent>' . base64_encode($publicExponent) . "</Exponent>\r\n" .
+ '</RSAKeyValue>';
+ break;
+ case self::PUBLIC_FORMAT_OPENSSH:
+ // from <http://tools.ietf.org/html/rfc4253#page-15>:
+ // string "ssh-rsa"
+ // mpint e
+ // mpint n
+ $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
+ $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $this->comment;
+
+ return $RSAPublicKey;
+ default: // eg. self::PUBLIC_FORMAT_PKCS1_RAW or self::PUBLIC_FORMAT_PKCS1
+ // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
+ // RSAPublicKey ::= SEQUENCE {
+ // modulus INTEGER, -- n
+ // publicExponent INTEGER -- e
+ // }
+ $components = array(
+ 'modulus' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
+ 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
+ );
+
+ $RSAPublicKey = pack(
+ 'Ca*a*a*',
+ self::ASN1_SEQUENCE,
+ $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
+ $components['modulus'],
+ $components['publicExponent']
+ );
+
+ if ($this->publicKeyFormat == self::PUBLIC_FORMAT_PKCS1_RAW) {
+ $RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
+ chunk_split(base64_encode($RSAPublicKey), 64) .
+ '-----END RSA PUBLIC KEY-----';
+ } else {
+ // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
+ $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
+ $RSAPublicKey = chr(0) . $RSAPublicKey;
+ $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
+
+ $RSAPublicKey = pack(
+ 'Ca*a*',
+ self::ASN1_SEQUENCE,
+ $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)),
+ $rsaOID . $RSAPublicKey
+ );
+
+ $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
+ chunk_split(base64_encode($RSAPublicKey), 64) .
+ '-----END PUBLIC KEY-----';
+ }
+
+ return $RSAPublicKey;
+ }
+ }
+
+ /**
+ * Break a public or private key down into its constituant components
+ *
+ * @access private
+ * @see self::_convertPublicKey()
+ * @see self::_convertPrivateKey()
+ * @param string|array $key
+ * @param int $type
+ * @return array|bool
+ */
+ function _parseKey($key, $type)
+ {
+ if ($type != self::PUBLIC_FORMAT_RAW && !is_string($key)) {
+ return false;
+ }
+
+ switch ($type) {
+ case self::PUBLIC_FORMAT_RAW:
+ if (!is_array($key)) {
+ return false;
+ }
+ $components = array();
+ switch (true) {
+ case isset($key['e']):
+ $components['publicExponent'] = $key['e']->copy();
+ break;
+ case isset($key['exponent']):
+ $components['publicExponent'] = $key['exponent']->copy();
+ break;
+ case isset($key['publicExponent']):
+ $components['publicExponent'] = $key['publicExponent']->copy();
+ break;
+ case isset($key[0]):
+ $components['publicExponent'] = $key[0]->copy();
+ }
+ switch (true) {
+ case isset($key['n']):
+ $components['modulus'] = $key['n']->copy();
+ break;
+ case isset($key['modulo']):
+ $components['modulus'] = $key['modulo']->copy();
+ break;
+ case isset($key['modulus']):
+ $components['modulus'] = $key['modulus']->copy();
+ break;
+ case isset($key[1]):
+ $components['modulus'] = $key[1]->copy();
+ }
+ return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
+ case self::PRIVATE_FORMAT_PKCS1:
+ case self::PRIVATE_FORMAT_PKCS8:
+ case self::PUBLIC_FORMAT_PKCS1:
+ /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
+ "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
+ protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding
+ two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here:
+
+ http://tools.ietf.org/html/rfc1421#section-4.6.1.1
+ http://tools.ietf.org/html/rfc1421#section-4.6.1.3
+
+ DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
+ DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
+ function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
+ own implementation. ie. the implementation *is* the standard and any bugs that may exist in that
+ implementation are part of the standard, as well.
+
+ * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
+ if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
+ $iv = pack('H*', trim($matches[2]));
+ $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key
+ $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8)));
+ // remove the Proc-Type / DEK-Info sections as they're no longer needed
+ $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
+ $ciphertext = $this->_extractBER($key);
+ if ($ciphertext === false) {
+ $ciphertext = $key;
+ }
+ switch ($matches[1]) {
+ case 'AES-256-CBC':
+ $crypto = new AES();
+ break;
+ case 'AES-128-CBC':
+ $symkey = substr($symkey, 0, 16);
+ $crypto = new AES();
+ break;
+ case 'DES-EDE3-CFB':
+ $crypto = new TripleDES(Base::MODE_CFB);
+ break;
+ case 'DES-EDE3-CBC':
+ $symkey = substr($symkey, 0, 24);
+ $crypto = new TripleDES();
+ break;
+ case 'DES-CBC':
+ $crypto = new DES();
+ break;
+ default:
+ return false;
+ }
+ $crypto->setKey($symkey);
+ $crypto->setIV($iv);
+ $decoded = $crypto->decrypt($ciphertext);
+ } else {
+ $decoded = $this->_extractBER($key);
+ }
+
+ if ($decoded !== false) {
+ $key = $decoded;
+ }
+
+ $components = array();
+
+ if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
+ return false;
+ }
+ if ($this->_decodeLength($key) != strlen($key)) {
+ return false;
+ }
+
+ $tag = ord($this->_string_shift($key));
+ /* intended for keys for which OpenSSL's asn1parse returns the following:
+
+ 0:d=0 hl=4 l= 631 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: INTEGER :00
+ 7:d=1 hl=2 l= 13 cons: SEQUENCE
+ 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 20:d=2 hl=2 l= 0 prim: NULL
+ 22:d=1 hl=4 l= 609 prim: OCTET STRING
+
+ ie. PKCS8 keys*/
+
+ if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
+ $this->_string_shift($key, 3);
+ $tag = self::ASN1_SEQUENCE;
+ }
+
+ if ($tag == self::ASN1_SEQUENCE) {
+ $temp = $this->_string_shift($key, $this->_decodeLength($key));
+ if (ord($this->_string_shift($temp)) != self::ASN1_OBJECT) {
+ return false;
+ }
+ $length = $this->_decodeLength($temp);
+ switch ($this->_string_shift($temp, $length)) {
+ case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
+ break;
+ case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
+ /*
+ PBEParameter ::= SEQUENCE {
+ salt OCTET STRING (SIZE(8)),
+ iterationCount INTEGER }
+ */
+ if (ord($this->_string_shift($temp)) != self::ASN1_SEQUENCE) {
+ return false;
+ }
+ if ($this->_decodeLength($temp) != strlen($temp)) {
+ return false;
+ }
+ $this->_string_shift($temp); // assume it's an octet string
+ $salt = $this->_string_shift($temp, $this->_decodeLength($temp));
+ if (ord($this->_string_shift($temp)) != self::ASN1_INTEGER) {
+ return false;
+ }
+ $this->_decodeLength($temp);
+ list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT));
+ $this->_string_shift($key); // assume it's an octet string
+ $length = $this->_decodeLength($key);
+ if (strlen($key) != $length) {
+ return false;
+ }
+
+ $crypto = new DES();
+ $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
+ $key = $crypto->decrypt($key);
+ if ($key === false) {
+ return false;
+ }
+ return $this->_parseKey($key, self::PRIVATE_FORMAT_PKCS1);
+ default:
+ return false;
+ }
+ /* intended for keys for which OpenSSL's asn1parse returns the following:
+
+ 0:d=0 hl=4 l= 290 cons: SEQUENCE
+ 4:d=1 hl=2 l= 13 cons: SEQUENCE
+ 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 17:d=2 hl=2 l= 0 prim: NULL
+ 19:d=1 hl=4 l= 271 prim: BIT STRING */
+ $tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag
+ $this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length
+ // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of
+ // unused bits in the final subsequent octet. The number shall be in the range zero to seven."
+ // -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2)
+ if ($tag == self::ASN1_BITSTRING) {
+ $this->_string_shift($key);
+ }
+ if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
+ return false;
+ }
+ if ($this->_decodeLength($key) != strlen($key)) {
+ return false;
+ }
+ $tag = ord($this->_string_shift($key));
+ }
+ if ($tag != self::ASN1_INTEGER) {
+ return false;
+ }
+
+ $length = $this->_decodeLength($key);
+ $temp = $this->_string_shift($key, $length);
+ if (strlen($temp) != 1 || ord($temp) > 2) {
+ $components['modulus'] = new BigInteger($temp, 256);
+ $this->_string_shift($key); // skip over self::ASN1_INTEGER
+ $length = $this->_decodeLength($key);
+ $components[$type == self::PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new BigInteger($this->_string_shift($key, $length), 256);
+
+ return $components;
+ }
+ if (ord($this->_string_shift($key)) != self::ASN1_INTEGER) {
+ return false;
+ }
+ $length = $this->_decodeLength($key);
+ $components['modulus'] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['publicExponent'] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['privateExponent'] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['primes'] = array(1 => new BigInteger($this->_string_shift($key, $length), 256));
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['primes'][] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['exponents'] = array(1 => new BigInteger($this->_string_shift($key, $length), 256));
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['exponents'][] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['coefficients'] = array(2 => new BigInteger($this->_string_shift($key, $length), 256));
+
+ if (!empty($key)) {
+ if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
+ return false;
+ }
+ $this->_decodeLength($key);
+ while (!empty($key)) {
+ if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
+ return false;
+ }
+ $this->_decodeLength($key);
+ $key = substr($key, 1);
+ $length = $this->_decodeLength($key);
+ $components['primes'][] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['exponents'][] = new BigInteger($this->_string_shift($key, $length), 256);
+ $this->_string_shift($key);
+ $length = $this->_decodeLength($key);
+ $components['coefficients'][] = new BigInteger($this->_string_shift($key, $length), 256);
+ }
+ }
+
+ return $components;
+ case self::PUBLIC_FORMAT_OPENSSH:
+ $parts = explode(' ', $key, 3);
+
+ $key = isset($parts[1]) ? base64_decode($parts[1]) : false;
+ if ($key === false) {
+ return false;
+ }
+
+ $comment = isset($parts[2]) ? $parts[2] : false;
+
+ $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa";
+
+ if (strlen($key) <= 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($key, 4)));
+ $publicExponent = new BigInteger($this->_string_shift($key, $length), -256);
+ if (strlen($key) <= 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($key, 4)));
+ $modulus = new BigInteger($this->_string_shift($key, $length), -256);
+
+ if ($cleanup && strlen($key)) {
+ if (strlen($key) <= 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($key, 4)));
+ $realModulus = new BigInteger($this->_string_shift($key, $length), -256);
+ return strlen($key) ? false : array(
+ 'modulus' => $realModulus,
+ 'publicExponent' => $modulus,
+ 'comment' => $comment
+ );
+ } else {
+ return strlen($key) ? false : array(
+ 'modulus' => $modulus,
+ 'publicExponent' => $publicExponent,
+ 'comment' => $comment
+ );
+ }
+ // http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
+ // http://en.wikipedia.org/wiki/XML_Signature
+ case self::PRIVATE_FORMAT_XML:
+ case self::PUBLIC_FORMAT_XML:
+ $this->components = array();
+
+ $xml = xml_parser_create('UTF-8');
+ xml_set_object($xml, $this);
+ xml_set_element_handler($xml, '_start_element_handler', '_stop_element_handler');
+ xml_set_character_data_handler($xml, '_data_handler');
+ // add <xml></xml> to account for "dangling" tags like <BitStrength>...</BitStrength> that are sometimes added
+ if (!xml_parse($xml, '<xml>' . $key . '</xml>')) {
+ xml_parser_free($xml);
+ unset($xml);
+ return false;
+ }
+
+ xml_parser_free($xml);
+ unset($xml);
+
+ return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false;
+ // from PuTTY's SSHPUBK.C
+ case self::PRIVATE_FORMAT_PUTTY:
+ $components = array();
+ $key = preg_split('#\r\n|\r|\n#', $key);
+ $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
+ if ($type != 'ssh-rsa') {
+ return false;
+ }
+ $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
+ $comment = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
+
+ $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
+ $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
+ $public = substr($public, 11);
+ extract(unpack('Nlength', $this->_string_shift($public, 4)));
+ $components['publicExponent'] = new BigInteger($this->_string_shift($public, $length), -256);
+ extract(unpack('Nlength', $this->_string_shift($public, 4)));
+ $components['modulus'] = new BigInteger($this->_string_shift($public, $length), -256);
+
+ $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4]));
+ $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
+
+ switch ($encryption) {
+ case 'aes256-cbc':
+ $symkey = '';
+ $sequence = 0;
+ while (strlen($symkey) < 32) {
+ $temp = pack('Na*', $sequence++, $this->password);
+ $symkey.= pack('H*', sha1($temp));
+ }
+ $symkey = substr($symkey, 0, 32);
+ $crypto = new AES();
+ }
+
+ if ($encryption != 'none') {
+ $crypto->setKey($symkey);
+ $crypto->disablePadding();
+ $private = $crypto->decrypt($private);
+ if ($private === false) {
+ return false;
+ }
+ }
+
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
+ if (strlen($private) < $length) {
+ return false;
+ }
+ $components['privateExponent'] = new BigInteger($this->_string_shift($private, $length), -256);
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
+ if (strlen($private) < $length) {
+ return false;
+ }
+ $components['primes'] = array(1 => new BigInteger($this->_string_shift($private, $length), -256));
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
+ if (strlen($private) < $length) {
+ return false;
+ }
+ $components['primes'][] = new BigInteger($this->_string_shift($private, $length), -256);
+
+ $temp = $components['primes'][1]->subtract($this->one);
+ $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp));
+ $temp = $components['primes'][2]->subtract($this->one);
+ $components['exponents'][] = $components['publicExponent']->modInverse($temp);
+
+ extract(unpack('Nlength', $this->_string_shift($private, 4)));
+ if (strlen($private) < $length) {
+ return false;
+ }
+ $components['coefficients'] = array(2 => new BigInteger($this->_string_shift($private, $length), -256));
+
+ return $components;
+ case self::PRIVATE_FORMAT_OPENSSH:
+ $components = array();
+ $decoded = $this->_extractBER($key);
+ $magic = $this->_string_shift($decoded, 15);
+ if ($magic !== "openssh-key-v1\0") {
+ return false;
+ }
+ $options = $this->_string_shift($decoded, 24);
+ // \0\0\0\4none = ciphername
+ // \0\0\0\4none = kdfname
+ // \0\0\0\0 = kdfoptions
+ // \0\0\0\1 = numkeys
+ if ($options != "\0\0\0\4none\0\0\0\4none\0\0\0\0\0\0\0\1") {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
+ if (strlen($decoded) < $length) {
+ return false;
+ }
+ $publicKey = $this->_string_shift($decoded, $length);
+ extract(unpack('Nlength', $this->_string_shift($decoded, 4)));
+ if (strlen($decoded) < $length) {
+ return false;
+ }
+ $paddedKey = $this->_string_shift($decoded, $length);
+
+ if ($this->_string_shift($publicKey, 11) !== "\0\0\0\7ssh-rsa") {
+ return false;
+ }
+
+ $checkint1 = $this->_string_shift($paddedKey, 4);
+ $checkint2 = $this->_string_shift($paddedKey, 4);
+ if (strlen($checkint1) != 4 || $checkint1 !== $checkint2) {
+ return false;
+ }
+
+ if ($this->_string_shift($paddedKey, 11) !== "\0\0\0\7ssh-rsa") {
+ return false;
+ }
+
+ $values = array(
+ &$components['modulus'],
+ &$components['publicExponent'],
+ &$components['privateExponent'],
+ &$components['coefficients'][2],
+ &$components['primes'][1],
+ &$components['primes'][2]
+ );
+
+ foreach ($values as &$value) {
+ extract(unpack('Nlength', $this->_string_shift($paddedKey, 4)));
+ if (strlen($paddedKey) < $length) {
+ return false;
+ }
+ $value = new BigInteger($this->_string_shift($paddedKey, $length), -256);
+ }
+
+ extract(unpack('Nlength', $this->_string_shift($paddedKey, 4)));
+ if (strlen($paddedKey) < $length) {
+ return false;
+ }
+ $components['comment'] = $this->_string_shift($decoded, $length);
+
+ $temp = $components['primes'][1]->subtract($this->one);
+ $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp));
+ $temp = $components['primes'][2]->subtract($this->one);
+ $components['exponents'][] = $components['publicExponent']->modInverse($temp);
+
+ return $components;
+ }
+ }
+
+ /**
+ * Returns the key size
+ *
+ * More specifically, this returns the size of the modulo in bits.
+ *
+ * @access public
+ * @return int
+ */
+ function getSize()
+ {
+ return !isset($this->modulus) ? 0 : strlen($this->modulus->toBits());
+ }
+
+ /**
+ * Start Element Handler
+ *
+ * Called by xml_set_element_handler()
+ *
+ * @access private
+ * @param resource $parser
+ * @param string $name
+ * @param array $attribs
+ */
+ function _start_element_handler($parser, $name, $attribs)
+ {
+ //$name = strtoupper($name);
+ switch ($name) {
+ case 'MODULUS':
+ $this->current = &$this->components['modulus'];
+ break;
+ case 'EXPONENT':
+ $this->current = &$this->components['publicExponent'];
+ break;
+ case 'P':
+ $this->current = &$this->components['primes'][1];
+ break;
+ case 'Q':
+ $this->current = &$this->components['primes'][2];
+ break;
+ case 'DP':
+ $this->current = &$this->components['exponents'][1];
+ break;
+ case 'DQ':
+ $this->current = &$this->components['exponents'][2];
+ break;
+ case 'INVERSEQ':
+ $this->current = &$this->components['coefficients'][2];
+ break;
+ case 'D':
+ $this->current = &$this->components['privateExponent'];
+ }
+ $this->current = '';
+ }
+
+ /**
+ * Stop Element Handler
+ *
+ * Called by xml_set_element_handler()
+ *
+ * @access private
+ * @param resource $parser
+ * @param string $name
+ */
+ function _stop_element_handler($parser, $name)
+ {
+ if (isset($this->current)) {
+ $this->current = new BigInteger(base64_decode($this->current), 256);
+ unset($this->current);
+ }
+ }
+
+ /**
+ * Data Handler
+ *
+ * Called by xml_set_character_data_handler()
+ *
+ * @access private
+ * @param resource $parser
+ * @param string $data
+ */
+ function _data_handler($parser, $data)
+ {
+ if (!isset($this->current) || is_object($this->current)) {
+ return;
+ }
+ $this->current.= trim($data);
+ }
+
+ /**
+ * Loads a public or private key
+ *
+ * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
+ *
+ * @access public
+ * @param string|RSA|array $key
+ * @param bool|int $type optional
+ * @return bool
+ */
+ function loadKey($key, $type = false)
+ {
+ if ($key instanceof RSA) {
+ $this->privateKeyFormat = $key->privateKeyFormat;
+ $this->publicKeyFormat = $key->publicKeyFormat;
+ $this->k = $key->k;
+ $this->hLen = $key->hLen;
+ $this->sLen = $key->sLen;
+ $this->mgfHLen = $key->mgfHLen;
+ $this->encryptionMode = $key->encryptionMode;
+ $this->signatureMode = $key->signatureMode;
+ $this->password = $key->password;
+ $this->configFile = $key->configFile;
+ $this->comment = $key->comment;
+
+ if (is_object($key->hash)) {
+ $this->hash = new Hash($key->hash->getHash());
+ }
+ if (is_object($key->mgfHash)) {
+ $this->mgfHash = new Hash($key->mgfHash->getHash());
+ }
+
+ if (is_object($key->modulus)) {
+ $this->modulus = $key->modulus->copy();
+ }
+ if (is_object($key->exponent)) {
+ $this->exponent = $key->exponent->copy();
+ }
+ if (is_object($key->publicExponent)) {
+ $this->publicExponent = $key->publicExponent->copy();
+ }
+
+ $this->primes = array();
+ $this->exponents = array();
+ $this->coefficients = array();
+
+ foreach ($this->primes as $prime) {
+ $this->primes[] = $prime->copy();
+ }
+ foreach ($this->exponents as $exponent) {
+ $this->exponents[] = $exponent->copy();
+ }
+ foreach ($this->coefficients as $coefficient) {
+ $this->coefficients[] = $coefficient->copy();
+ }
+
+ return true;
+ }
+
+ if ($type === false) {
+ $types = array(
+ self::PUBLIC_FORMAT_RAW,
+ self::PRIVATE_FORMAT_PKCS1,
+ self::PRIVATE_FORMAT_XML,
+ self::PRIVATE_FORMAT_PUTTY,
+ self::PUBLIC_FORMAT_OPENSSH,
+ self::PRIVATE_FORMAT_OPENSSH
+ );
+ foreach ($types as $type) {
+ $components = $this->_parseKey($key, $type);
+ if ($components !== false) {
+ break;
+ }
+ }
+ } else {
+ $components = $this->_parseKey($key, $type);
+ }
+
+ if ($components === false) {
+ $this->comment = null;
+ $this->modulus = null;
+ $this->k = null;
+ $this->exponent = null;
+ $this->primes = null;
+ $this->exponents = null;
+ $this->coefficients = null;
+ $this->publicExponent = null;
+
+ return false;
+ }
+
+ if (isset($components['comment']) && $components['comment'] !== false) {
+ $this->comment = $components['comment'];
+ }
+ $this->modulus = $components['modulus'];
+ $this->k = strlen($this->modulus->toBytes());
+ $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
+ if (isset($components['primes'])) {
+ $this->primes = $components['primes'];
+ $this->exponents = $components['exponents'];
+ $this->coefficients = $components['coefficients'];
+ $this->publicExponent = $components['publicExponent'];
+ } else {
+ $this->primes = array();
+ $this->exponents = array();
+ $this->coefficients = array();
+ $this->publicExponent = false;
+ }
+
+ switch ($type) {
+ case self::PUBLIC_FORMAT_OPENSSH:
+ case self::PUBLIC_FORMAT_RAW:
+ $this->setPublicKey();
+ break;
+ case self::PRIVATE_FORMAT_PKCS1:
+ switch (true) {
+ case strpos($key, '-BEGIN PUBLIC KEY-') !== false:
+ case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false:
+ $this->setPublicKey();
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the password
+ *
+ * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false.
+ * Or rather, pass in $password such that empty($password) && !is_string($password) is true.
+ *
+ * @see self::createKey()
+ * @see self::loadKey()
+ * @access public
+ * @param string $password
+ */
+ function setPassword($password = false)
+ {
+ $this->password = $password;
+ }
+
+ /**
+ * Defines the public key
+ *
+ * Some private key formats define the public exponent and some don't. Those that don't define it are problematic when
+ * used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a
+ * message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys
+ * and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public
+ * exponent this won't work unless you manually add the public exponent. phpseclib tries to guess if the key being used
+ * is the public key but in the event that it guesses incorrectly you might still want to explicitly set the key as being
+ * public.
+ *
+ * Do note that when a new key is loaded the index will be cleared.
+ *
+ * Returns true on success, false on failure
+ *
+ * @see self::getPublicKey()
+ * @access public
+ * @param string $key optional
+ * @param int $type optional
+ * @return bool
+ */
+ function setPublicKey($key = false, $type = false)
+ {
+ // if a public key has already been loaded return false
+ if (!empty($this->publicExponent)) {
+ return false;
+ }
+
+ if ($key === false && !empty($this->modulus)) {
+ $this->publicExponent = $this->exponent;
+ return true;
+ }
+
+ if ($type === false) {
+ $types = array(
+ self::PUBLIC_FORMAT_RAW,
+ self::PUBLIC_FORMAT_PKCS1,
+ self::PUBLIC_FORMAT_XML,
+ self::PUBLIC_FORMAT_OPENSSH
+ );
+ foreach ($types as $type) {
+ $components = $this->_parseKey($key, $type);
+ if ($components !== false) {
+ break;
+ }
+ }
+ } else {
+ $components = $this->_parseKey($key, $type);
+ }
+
+ if ($components === false) {
+ return false;
+ }
+
+ if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
+ $this->modulus = $components['modulus'];
+ $this->exponent = $this->publicExponent = $components['publicExponent'];
+ return true;
+ }
+
+ $this->publicExponent = $components['publicExponent'];
+
+ return true;
+ }
+
+ /**
+ * Defines the private key
+ *
+ * If phpseclib guessed a private key was a public key and loaded it as such it might be desirable to force
+ * phpseclib to treat the key as a private key. This function will do that.
+ *
+ * Do note that when a new key is loaded the index will be cleared.
+ *
+ * Returns true on success, false on failure
+ *
+ * @see self::getPublicKey()
+ * @access public
+ * @param string $key optional
+ * @param int $type optional
+ * @return bool
+ */
+ function setPrivateKey($key = false, $type = false)
+ {
+ if ($key === false && !empty($this->publicExponent)) {
+ $this->publicExponent = false;
+ return true;
+ }
+
+ $rsa = new RSA();
+ if (!$rsa->loadKey($key, $type)) {
+ return false;
+ }
+ $rsa->publicExponent = false;
+
+ // don't overwrite the old key if the new key is invalid
+ $this->loadKey($rsa);
+ return true;
+ }
+
+ /**
+ * Returns the public key
+ *
+ * The public key is only returned under two circumstances - if the private key had the public key embedded within it
+ * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
+ * function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
+ *
+ * @see self::getPublicKey()
+ * @access public
+ * @param string $key
+ * @param int $type optional
+ */
+ function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8)
+ {
+ if (empty($this->modulus) || empty($this->publicExponent)) {
+ return false;
+ }
+
+ $oldFormat = $this->publicKeyFormat;
+ $this->publicKeyFormat = $type;
+ $temp = $this->_convertPublicKey($this->modulus, $this->publicExponent);
+ $this->publicKeyFormat = $oldFormat;
+ return $temp;
+ }
+
+ /**
+ * Returns the public key's fingerprint
+ *
+ * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
+ * no public key currently loaded, false is returned.
+ * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
+ *
+ * @access public
+ * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
+ * for invalid values.
+ * @return mixed
+ */
+ function getPublicKeyFingerprint($algorithm = 'md5')
+ {
+ if (empty($this->modulus) || empty($this->publicExponent)) {
+ return false;
+ }
+
+ $modulus = $this->modulus->toBytes(true);
+ $publicExponent = $this->publicExponent->toBytes(true);
+
+ $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
+
+ switch ($algorithm) {
+ case 'sha256':
+ $hash = new Hash('sha256');
+ $base = base64_encode($hash->hash($RSAPublicKey));
+ return substr($base, 0, strlen($base) - 1);
+ case 'md5':
+ return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Returns the private key
+ *
+ * The private key is only returned if the currently loaded key contains the constituent prime numbers.
+ *
+ * @see self::getPublicKey()
+ * @access public
+ * @param string $key
+ * @param int $type optional
+ * @return mixed
+ */
+ function getPrivateKey($type = self::PUBLIC_FORMAT_PKCS1)
+ {
+ if (empty($this->primes)) {
+ return false;
+ }
+
+ $oldFormat = $this->privateKeyFormat;
+ $this->privateKeyFormat = $type;
+ $temp = $this->_convertPrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients);
+ $this->privateKeyFormat = $oldFormat;
+ return $temp;
+ }
+
+ /**
+ * Returns a minimalistic private key
+ *
+ * Returns the private key without the prime number constituants. Structurally identical to a public key that
+ * hasn't been set as the public key
+ *
+ * @see self::getPrivateKey()
+ * @access private
+ * @param string $key
+ * @param int $type optional
+ */
+ function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8)
+ {
+ if (empty($this->modulus) || empty($this->exponent)) {
+ return false;
+ }
+
+ $oldFormat = $this->publicKeyFormat;
+ $this->publicKeyFormat = $mode;
+ $temp = $this->_convertPublicKey($this->modulus, $this->exponent);
+ $this->publicKeyFormat = $oldFormat;
+ return $temp;
+ }
+
+ /**
+ * __toString() magic method
+ *
+ * @access public
+ * @return string
+ */
+ function __toString()
+ {
+ $key = $this->getPrivateKey($this->privateKeyFormat);
+ if ($key !== false) {
+ return $key;
+ }
+ $key = $this->_getPrivatePublicKey($this->publicKeyFormat);
+ return $key !== false ? $key : '';
+ }
+
+ /**
+ * __clone() magic method
+ *
+ * @access public
+ * @return Crypt_RSA
+ */
+ function __clone()
+ {
+ $key = new RSA();
+ $key->loadKey($this);
+ return $key;
+ }
+
+ /**
+ * Generates the smallest and largest numbers requiring $bits bits
+ *
+ * @access private
+ * @param int $bits
+ * @return array
+ */
+ function _generateMinMax($bits)
+ {
+ $bytes = $bits >> 3;
+ $min = str_repeat(chr(0), $bytes);
+ $max = str_repeat(chr(0xFF), $bytes);
+ $msb = $bits & 7;
+ if ($msb) {
+ $min = chr(1 << ($msb - 1)) . $min;
+ $max = chr((1 << $msb) - 1) . $max;
+ } else {
+ $min[0] = chr(0x80);
+ }
+
+ return array(
+ 'min' => new BigInteger($min, 256),
+ 'max' => new BigInteger($max, 256)
+ );
+ }
+
+ /**
+ * DER-decode the length
+ *
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
+ *
+ * @access private
+ * @param string $string
+ * @return int
+ */
+ function _decodeLength(&$string)
+ {
+ $length = ord($this->_string_shift($string));
+ if ($length & 0x80) { // definite length, long form
+ $length&= 0x7F;
+ $temp = $this->_string_shift($string, $length);
+ list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
+ }
+ return $length;
+ }
+
+ /**
+ * DER-encode the length
+ *
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
+ *
+ * @access private
+ * @param int $length
+ * @return string
+ */
+ function _encodeLength($length)
+ {
+ if ($length <= 0x7F) {
+ return chr($length);
+ }
+
+ $temp = ltrim(pack('N', $length), chr(0));
+ return pack('Ca*', 0x80 | strlen($temp), $temp);
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @return string
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+
+ /**
+ * Determines the private key format
+ *
+ * @see self::createKey()
+ * @access public
+ * @param int $format
+ */
+ function setPrivateKeyFormat($format)
+ {
+ $this->privateKeyFormat = $format;
+ }
+
+ /**
+ * Determines the public key format
+ *
+ * @see self::createKey()
+ * @access public
+ * @param int $format
+ */
+ function setPublicKeyFormat($format)
+ {
+ $this->publicKeyFormat = $format;
+ }
+
+ /**
+ * Determines which hashing function should be used
+ *
+ * Used with signature production / verification and (if the encryption mode is self::ENCRYPTION_OAEP) encryption and
+ * decryption. If $hash isn't supported, sha1 is used.
+ *
+ * @access public
+ * @param string $hash
+ */
+ function setHash($hash)
+ {
+ // \phpseclib\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
+ switch ($hash) {
+ case 'md2':
+ case 'md5':
+ case 'sha1':
+ case 'sha256':
+ case 'sha384':
+ case 'sha512':
+ $this->hash = new Hash($hash);
+ $this->hashName = $hash;
+ break;
+ default:
+ $this->hash = new Hash('sha1');
+ $this->hashName = 'sha1';
+ }
+ $this->hLen = $this->hash->getLength();
+ }
+
+ /**
+ * Determines which hashing function should be used for the mask generation function
+ *
+ * The mask generation function is used by self::ENCRYPTION_OAEP and self::SIGNATURE_PSS and although it's
+ * best if Hash and MGFHash are set to the same thing this is not a requirement.
+ *
+ * @access public
+ * @param string $hash
+ */
+ function setMGFHash($hash)
+ {
+ // \phpseclib\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
+ switch ($hash) {
+ case 'md2':
+ case 'md5':
+ case 'sha1':
+ case 'sha256':
+ case 'sha384':
+ case 'sha512':
+ $this->mgfHash = new Hash($hash);
+ break;
+ default:
+ $this->mgfHash = new Hash('sha1');
+ }
+ $this->mgfHLen = $this->mgfHash->getLength();
+ }
+
+ /**
+ * Determines the salt length
+ *
+ * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
+ *
+ * Typical salt lengths in octets are hLen (the length of the output
+ * of the hash function Hash) and 0.
+ *
+ * @access public
+ * @param int $format
+ */
+ function setSaltLength($sLen)
+ {
+ $this->sLen = $sLen;
+ }
+
+ /**
+ * Integer-to-Octet-String primitive
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $x
+ * @param int $xLen
+ * @return string
+ */
+ function _i2osp($x, $xLen)
+ {
+ $x = $x->toBytes();
+ if (strlen($x) > $xLen) {
+ user_error('Integer too large');
+ return false;
+ }
+ return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
+ }
+
+ /**
+ * Octet-String-to-Integer primitive
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
+ *
+ * @access private
+ * @param string $x
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _os2ip($x)
+ {
+ return new BigInteger($x, 256);
+ }
+
+ /**
+ * Exponentiate with or without Chinese Remainder Theorem
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.2}.
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $x
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _exponentiate($x)
+ {
+ switch (true) {
+ case empty($this->primes):
+ case $this->primes[1]->equals($this->zero):
+ case empty($this->coefficients):
+ case $this->coefficients[2]->equals($this->zero):
+ case empty($this->exponents):
+ case $this->exponents[1]->equals($this->zero):
+ return $x->modPow($this->exponent, $this->modulus);
+ }
+
+ $num_primes = count($this->primes);
+
+ if (defined('CRYPT_RSA_DISABLE_BLINDING')) {
+ $m_i = array(
+ 1 => $x->modPow($this->exponents[1], $this->primes[1]),
+ 2 => $x->modPow($this->exponents[2], $this->primes[2])
+ );
+ $h = $m_i[1]->subtract($m_i[2]);
+ $h = $h->multiply($this->coefficients[2]);
+ list(, $h) = $h->divide($this->primes[1]);
+ $m = $m_i[2]->add($h->multiply($this->primes[2]));
+
+ $r = $this->primes[1];
+ for ($i = 3; $i <= $num_primes; $i++) {
+ $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
+
+ $r = $r->multiply($this->primes[$i - 1]);
+
+ $h = $m_i->subtract($m);
+ $h = $h->multiply($this->coefficients[$i]);
+ list(, $h) = $h->divide($this->primes[$i]);
+
+ $m = $m->add($r->multiply($h));
+ }
+ } else {
+ $smallest = $this->primes[1];
+ for ($i = 2; $i <= $num_primes; $i++) {
+ if ($smallest->compare($this->primes[$i]) > 0) {
+ $smallest = $this->primes[$i];
+ }
+ }
+
+ $one = new BigInteger(1);
+
+ $r = $one->random($one, $smallest->subtract($one));
+
+ $m_i = array(
+ 1 => $this->_blind($x, $r, 1),
+ 2 => $this->_blind($x, $r, 2)
+ );
+ $h = $m_i[1]->subtract($m_i[2]);
+ $h = $h->multiply($this->coefficients[2]);
+ list(, $h) = $h->divide($this->primes[1]);
+ $m = $m_i[2]->add($h->multiply($this->primes[2]));
+
+ $r = $this->primes[1];
+ for ($i = 3; $i <= $num_primes; $i++) {
+ $m_i = $this->_blind($x, $r, $i);
+
+ $r = $r->multiply($this->primes[$i - 1]);
+
+ $h = $m_i->subtract($m);
+ $h = $h->multiply($this->coefficients[$i]);
+ list(, $h) = $h->divide($this->primes[$i]);
+
+ $m = $m->add($r->multiply($h));
+ }
+ }
+
+ return $m;
+ }
+
+ /**
+ * Performs RSA Blinding
+ *
+ * Protects against timing attacks by employing RSA Blinding.
+ * Returns $x->modPow($this->exponents[$i], $this->primes[$i])
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $x
+ * @param \phpseclib\Math\BigInteger $r
+ * @param int $i
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _blind($x, $r, $i)
+ {
+ $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
+ $x = $x->modPow($this->exponents[$i], $this->primes[$i]);
+
+ $r = $r->modInverse($this->primes[$i]);
+ $x = $x->multiply($r);
+ list(, $x) = $x->divide($this->primes[$i]);
+
+ return $x;
+ }
+
+ /**
+ * Performs blinded RSA equality testing
+ *
+ * Protects against a particular type of timing attack described.
+ *
+ * See {@link http://codahale.com/a-lesson-in-timing-attacks/ A Lesson In Timing Attacks (or, Don't use MessageDigest.isEquals)}
+ *
+ * Thanks for the heads up singpolyma!
+ *
+ * @access private
+ * @param string $x
+ * @param string $y
+ * @return bool
+ */
+ function _equals($x, $y)
+ {
+ if (function_exists('hash_equals')) {
+ return hash_equals($x, $y);
+ }
+
+ if (strlen($x) != strlen($y)) {
+ return false;
+ }
+
+ $result = "\0";
+ $x^= $y;
+ for ($i = 0; $i < strlen($x); $i++) {
+ $result|= $x[$i];
+ }
+
+ return $result === "\0";
+ }
+
+ /**
+ * RSAEP
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $m
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _rsaep($m)
+ {
+ if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
+ user_error('Message representative out of range');
+ return false;
+ }
+ return $this->_exponentiate($m);
+ }
+
+ /**
+ * RSADP
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $c
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _rsadp($c)
+ {
+ if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) {
+ user_error('Ciphertext representative out of range');
+ return false;
+ }
+ return $this->_exponentiate($c);
+ }
+
+ /**
+ * RSASP1
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $m
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _rsasp1($m)
+ {
+ if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
+ user_error('Message representative out of range');
+ return false;
+ }
+ return $this->_exponentiate($m);
+ }
+
+ /**
+ * RSAVP1
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
+ *
+ * @access private
+ * @param \phpseclib\Math\BigInteger $s
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _rsavp1($s)
+ {
+ if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
+ user_error('Signature representative out of range');
+ return false;
+ }
+ return $this->_exponentiate($s);
+ }
+
+ /**
+ * MGF1
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
+ *
+ * @access private
+ * @param string $mgfSeed
+ * @param int $mgfLen
+ * @return string
+ */
+ function _mgf1($mgfSeed, $maskLen)
+ {
+ // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
+
+ $t = '';
+ $count = ceil($maskLen / $this->mgfHLen);
+ for ($i = 0; $i < $count; $i++) {
+ $c = pack('N', $i);
+ $t.= $this->mgfHash->hash($mgfSeed . $c);
+ }
+
+ return substr($t, 0, $maskLen);
+ }
+
+ /**
+ * RSAES-OAEP-ENCRYPT
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and
+ * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
+ *
+ * @access private
+ * @param string $m
+ * @param string $l
+ * @return string
+ */
+ function _rsaes_oaep_encrypt($m, $l = '')
+ {
+ $mLen = strlen($m);
+
+ // Length checking
+
+ // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
+ // be output.
+
+ if ($mLen > $this->k - 2 * $this->hLen - 2) {
+ user_error('Message too long');
+ return false;
+ }
+
+ // EME-OAEP encoding
+
+ $lHash = $this->hash->hash($l);
+ $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
+ $db = $lHash . $ps . chr(1) . $m;
+ $seed = Random::string($this->hLen);
+ $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
+ $maskedDB = $db ^ $dbMask;
+ $seedMask = $this->_mgf1($maskedDB, $this->hLen);
+ $maskedSeed = $seed ^ $seedMask;
+ $em = chr(0) . $maskedSeed . $maskedDB;
+
+ // RSA encryption
+
+ $m = $this->_os2ip($em);
+ $c = $this->_rsaep($m);
+ $c = $this->_i2osp($c, $this->k);
+
+ // Output the ciphertext C
+
+ return $c;
+ }
+
+ /**
+ * RSAES-OAEP-DECRYPT
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error
+ * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2:
+ *
+ * Note. Care must be taken to ensure that an opponent cannot
+ * distinguish the different error conditions in Step 3.g, whether by
+ * error message or timing, or, more generally, learn partial
+ * information about the encoded message EM. Otherwise an opponent may
+ * be able to obtain useful information about the decryption of the
+ * ciphertext C, leading to a chosen-ciphertext attack such as the one
+ * observed by Manger [36].
+ *
+ * As for $l... to quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
+ *
+ * Both the encryption and the decryption operations of RSAES-OAEP take
+ * the value of a label L as input. In this version of PKCS #1, L is
+ * the empty string; other uses of the label are outside the scope of
+ * this document.
+ *
+ * @access private
+ * @param string $c
+ * @param string $l
+ * @return string
+ */
+ function _rsaes_oaep_decrypt($c, $l = '')
+ {
+ // Length checking
+
+ // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
+ // be output.
+
+ if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
+ user_error('Decryption error');
+ return false;
+ }
+
+ // RSA decryption
+
+ $c = $this->_os2ip($c);
+ $m = $this->_rsadp($c);
+ if ($m === false) {
+ user_error('Decryption error');
+ return false;
+ }
+ $em = $this->_i2osp($m, $this->k);
+
+ // EME-OAEP decoding
+
+ $lHash = $this->hash->hash($l);
+ $y = ord($em[0]);
+ $maskedSeed = substr($em, 1, $this->hLen);
+ $maskedDB = substr($em, $this->hLen + 1);
+ $seedMask = $this->_mgf1($maskedDB, $this->hLen);
+ $seed = $maskedSeed ^ $seedMask;
+ $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
+ $db = $maskedDB ^ $dbMask;
+ $lHash2 = substr($db, 0, $this->hLen);
+ $m = substr($db, $this->hLen);
+ $hashesMatch = $this->_equals($lHash, $lHash2);
+ $leadingZeros = 1;
+ $patternMatch = 0;
+ $offset = 0;
+ for ($i = 0; $i < strlen($m); $i++) {
+ $patternMatch|= $leadingZeros & ($m[$i] === "\1");
+ $leadingZeros&= $m[$i] === "\0";
+ $offset+= $patternMatch ? 0 : 1;
+ }
+
+ // we do & instead of && to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation
+ // to protect against timing attacks
+ if (!$hashesMatch & !$patternMatch) {
+ user_error('Decryption error');
+ return false;
+ }
+
+ // Output the message M
+
+ return substr($m, $offset + 1);
+ }
+
+ /**
+ * Raw Encryption / Decryption
+ *
+ * Doesn't use padding and is not recommended.
+ *
+ * @access private
+ * @param string $m
+ * @return string
+ */
+ function _raw_encrypt($m)
+ {
+ $temp = $this->_os2ip($m);
+ $temp = $this->_rsaep($temp);
+ return $this->_i2osp($temp, $this->k);
+ }
+
+ /**
+ * RSAES-PKCS1-V1_5-ENCRYPT
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
+ *
+ * @access private
+ * @param string $m
+ * @return string
+ */
+ function _rsaes_pkcs1_v1_5_encrypt($m)
+ {
+ $mLen = strlen($m);
+
+ // Length checking
+
+ if ($mLen > $this->k - 11) {
+ user_error('Message too long');
+ return false;
+ }
+
+ // EME-PKCS1-v1_5 encoding
+
+ $psLen = $this->k - $mLen - 3;
+ $ps = '';
+ while (strlen($ps) != $psLen) {
+ $temp = Random::string($psLen - strlen($ps));
+ $temp = str_replace("\x00", '', $temp);
+ $ps.= $temp;
+ }
+ $type = 2;
+ // see the comments of _rsaes_pkcs1_v1_5_decrypt() to understand why this is being done
+ if (defined('CRYPT_RSA_PKCS15_COMPAT') && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) {
+ $type = 1;
+ // "The padding string PS shall consist of k-3-||D|| octets. ... for block type 01, they shall have value FF"
+ $ps = str_repeat("\xFF", $psLen);
+ }
+ $em = chr(0) . chr($type) . $ps . chr(0) . $m;
+
+ // RSA encryption
+ $m = $this->_os2ip($em);
+ $c = $this->_rsaep($m);
+ $c = $this->_i2osp($c, $this->k);
+
+ // Output the ciphertext C
+
+ return $c;
+ }
+
+ /**
+ * RSAES-PKCS1-V1_5-DECRYPT
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
+ *
+ * For compatibility purposes, this function departs slightly from the description given in RFC3447.
+ * The reason being that RFC2313#section-8.1 (PKCS#1 v1.5) states that ciphertext's encrypted by the
+ * private key should have the second byte set to either 0 or 1 and that ciphertext's encrypted by the
+ * public key should have the second byte set to 2. In RFC3447 (PKCS#1 v2.1), the second byte is supposed
+ * to be 2 regardless of which key is used. For compatibility purposes, we'll just check to make sure the
+ * second byte is 2 or less. If it is, we'll accept the decrypted string as valid.
+ *
+ * As a consequence of this, a private key encrypted ciphertext produced with \phpseclib\Crypt\RSA may not decrypt
+ * with a strictly PKCS#1 v1.5 compliant RSA implementation. Public key encrypted ciphertext's should but
+ * not private key encrypted ciphertext's.
+ *
+ * @access private
+ * @param string $c
+ * @return string
+ */
+ function _rsaes_pkcs1_v1_5_decrypt($c)
+ {
+ // Length checking
+
+ if (strlen($c) != $this->k) { // or if k < 11
+ user_error('Decryption error');
+ return false;
+ }
+
+ // RSA decryption
+
+ $c = $this->_os2ip($c);
+ $m = $this->_rsadp($c);
+
+ if ($m === false) {
+ user_error('Decryption error');
+ return false;
+ }
+ $em = $this->_i2osp($m, $this->k);
+
+ // EME-PKCS1-v1_5 decoding
+
+ if (ord($em[0]) != 0 || ord($em[1]) > 2) {
+ user_error('Decryption error');
+ return false;
+ }
+
+ $ps = substr($em, 2, strpos($em, chr(0), 2) - 2);
+ $m = substr($em, strlen($ps) + 3);
+
+ if (strlen($ps) < 8) {
+ user_error('Decryption error');
+ return false;
+ }
+
+ // Output M
+
+ return $m;
+ }
+
+ /**
+ * EMSA-PSS-ENCODE
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
+ *
+ * @access private
+ * @param string $m
+ * @param int $emBits
+ */
+ function _emsa_pss_encode($m, $emBits)
+ {
+ // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
+ // be output.
+
+ $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
+ $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
+
+ $mHash = $this->hash->hash($m);
+ if ($emLen < $this->hLen + $sLen + 2) {
+ user_error('Encoding error');
+ return false;
+ }
+
+ $salt = Random::string($sLen);
+ $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
+ $h = $this->hash->hash($m2);
+ $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2);
+ $db = $ps . chr(1) . $salt;
+ $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1);
+ $maskedDB = $db ^ $dbMask;
+ $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0];
+ $em = $maskedDB . $h . chr(0xBC);
+
+ return $em;
+ }
+
+ /**
+ * EMSA-PSS-VERIFY
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
+ *
+ * @access private
+ * @param string $m
+ * @param string $em
+ * @param int $emBits
+ * @return string
+ */
+ function _emsa_pss_verify($m, $em, $emBits)
+ {
+ // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
+ // be output.
+
+ $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8);
+ $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
+
+ $mHash = $this->hash->hash($m);
+ if ($emLen < $this->hLen + $sLen + 2) {
+ return false;
+ }
+
+ if ($em[strlen($em) - 1] != chr(0xBC)) {
+ return false;
+ }
+
+ $maskedDB = substr($em, 0, -$this->hLen - 1);
+ $h = substr($em, -$this->hLen - 1, $this->hLen);
+ $temp = chr(0xFF << ($emBits & 7));
+ if ((~$maskedDB[0] & $temp) != $temp) {
+ return false;
+ }
+ $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1);
+ $db = $maskedDB ^ $dbMask;
+ $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0];
+ $temp = $emLen - $this->hLen - $sLen - 2;
+ if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
+ return false;
+ }
+ $salt = substr($db, $temp + 1); // should be $sLen long
+ $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
+ $h2 = $this->hash->hash($m2);
+ return $this->_equals($h, $h2);
+ }
+
+ /**
+ * RSASSA-PSS-SIGN
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
+ *
+ * @access private
+ * @param string $m
+ * @return string
+ */
+ function _rsassa_pss_sign($m)
+ {
+ // EMSA-PSS encoding
+
+ $em = $this->_emsa_pss_encode($m, 8 * $this->k - 1);
+
+ // RSA signature
+
+ $m = $this->_os2ip($em);
+ $s = $this->_rsasp1($m);
+ $s = $this->_i2osp($s, $this->k);
+
+ // Output the signature S
+
+ return $s;
+ }
+
+ /**
+ * RSASSA-PSS-VERIFY
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
+ *
+ * @access private
+ * @param string $m
+ * @param string $s
+ * @return string
+ */
+ function _rsassa_pss_verify($m, $s)
+ {
+ // Length checking
+
+ if (strlen($s) != $this->k) {
+ user_error('Invalid signature');
+ return false;
+ }
+
+ // RSA verification
+
+ $modBits = 8 * $this->k;
+
+ $s2 = $this->_os2ip($s);
+ $m2 = $this->_rsavp1($s2);
+ if ($m2 === false) {
+ user_error('Invalid signature');
+ return false;
+ }
+ $em = $this->_i2osp($m2, $modBits >> 3);
+ if ($em === false) {
+ user_error('Invalid signature');
+ return false;
+ }
+
+ // EMSA-PSS verification
+
+ return $this->_emsa_pss_verify($m, $em, $modBits - 1);
+ }
+
+ /**
+ * EMSA-PKCS1-V1_5-ENCODE
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
+ *
+ * @access private
+ * @param string $m
+ * @param int $emLen
+ * @return string
+ */
+ function _emsa_pkcs1_v1_5_encode($m, $emLen)
+ {
+ $h = $this->hash->hash($m);
+ if ($h === false) {
+ return false;
+ }
+
+ // see http://tools.ietf.org/html/rfc3447#page-43
+ switch ($this->hashName) {
+ case 'md2':
+ $t = pack('H*', '3020300c06082a864886f70d020205000410');
+ break;
+ case 'md5':
+ $t = pack('H*', '3020300c06082a864886f70d020505000410');
+ break;
+ case 'sha1':
+ $t = pack('H*', '3021300906052b0e03021a05000414');
+ break;
+ case 'sha256':
+ $t = pack('H*', '3031300d060960864801650304020105000420');
+ break;
+ case 'sha384':
+ $t = pack('H*', '3041300d060960864801650304020205000430');
+ break;
+ case 'sha512':
+ $t = pack('H*', '3051300d060960864801650304020305000440');
+ }
+ $t.= $h;
+ $tLen = strlen($t);
+
+ if ($emLen < $tLen + 11) {
+ user_error('Intended encoded message length too short');
+ return false;
+ }
+
+ $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
+
+ $em = "\0\1$ps\0$t";
+
+ return $em;
+ }
+
+ /**
+ * RSASSA-PKCS1-V1_5-SIGN
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
+ *
+ * @access private
+ * @param string $m
+ * @return string
+ */
+ function _rsassa_pkcs1_v1_5_sign($m)
+ {
+ // EMSA-PKCS1-v1_5 encoding
+
+ $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
+ if ($em === false) {
+ user_error('RSA modulus too short');
+ return false;
+ }
+
+ // RSA signature
+
+ $m = $this->_os2ip($em);
+ $s = $this->_rsasp1($m);
+ $s = $this->_i2osp($s, $this->k);
+
+ // Output the signature S
+
+ return $s;
+ }
+
+ /**
+ * RSASSA-PKCS1-V1_5-VERIFY
+ *
+ * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
+ *
+ * @access private
+ * @param string $m
+ * @return string
+ */
+ function _rsassa_pkcs1_v1_5_verify($m, $s)
+ {
+ // Length checking
+
+ if (strlen($s) != $this->k) {
+ user_error('Invalid signature');
+ return false;
+ }
+
+ // RSA verification
+
+ $s = $this->_os2ip($s);
+ $m2 = $this->_rsavp1($s);
+ if ($m2 === false) {
+ user_error('Invalid signature');
+ return false;
+ }
+ $em = $this->_i2osp($m2, $this->k);
+ if ($em === false) {
+ user_error('Invalid signature');
+ return false;
+ }
+
+ // EMSA-PKCS1-v1_5 encoding
+
+ $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
+ if ($em2 === false) {
+ user_error('RSA modulus too short');
+ return false;
+ }
+
+ // Compare
+ return $this->_equals($em, $em2);
+ }
+
+ /**
+ * Set Encryption Mode
+ *
+ * Valid values include self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1.
+ *
+ * @access public
+ * @param int $mode
+ */
+ function setEncryptionMode($mode)
+ {
+ $this->encryptionMode = $mode;
+ }
+
+ /**
+ * Set Signature Mode
+ *
+ * Valid values include self::SIGNATURE_PSS and self::SIGNATURE_PKCS1
+ *
+ * @access public
+ * @param int $mode
+ */
+ function setSignatureMode($mode)
+ {
+ $this->signatureMode = $mode;
+ }
+
+ /**
+ * Set public key comment.
+ *
+ * @access public
+ * @param string $comment
+ */
+ function setComment($comment)
+ {
+ $this->comment = $comment;
+ }
+
+ /**
+ * Get public key comment.
+ *
+ * @access public
+ * @return string
+ */
+ function getComment()
+ {
+ return $this->comment;
+ }
+
+ /**
+ * Encryption
+ *
+ * Both self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1 both place limits on how long $plaintext can be.
+ * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
+ * be concatenated together.
+ *
+ * @see self::decrypt()
+ * @access public
+ * @param string $plaintext
+ * @return string
+ */
+ function encrypt($plaintext)
+ {
+ switch ($this->encryptionMode) {
+ case self::ENCRYPTION_NONE:
+ $plaintext = str_split($plaintext, $this->k);
+ $ciphertext = '';
+ foreach ($plaintext as $m) {
+ $ciphertext.= $this->_raw_encrypt($m);
+ }
+ return $ciphertext;
+ case self::ENCRYPTION_PKCS1:
+ $length = $this->k - 11;
+ if ($length <= 0) {
+ return false;
+ }
+
+ $plaintext = str_split($plaintext, $length);
+ $ciphertext = '';
+ foreach ($plaintext as $m) {
+ $ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m);
+ }
+ return $ciphertext;
+ //case self::ENCRYPTION_OAEP:
+ default:
+ $length = $this->k - 2 * $this->hLen - 2;
+ if ($length <= 0) {
+ return false;
+ }
+
+ $plaintext = str_split($plaintext, $length);
+ $ciphertext = '';
+ foreach ($plaintext as $m) {
+ $ciphertext.= $this->_rsaes_oaep_encrypt($m);
+ }
+ return $ciphertext;
+ }
+ }
+
+ /**
+ * Decryption
+ *
+ * @see self::encrypt()
+ * @access public
+ * @param string $plaintext
+ * @return string
+ */
+ function decrypt($ciphertext)
+ {
+ if ($this->k <= 0) {
+ return false;
+ }
+
+ $ciphertext = str_split($ciphertext, $this->k);
+ $ciphertext[count($ciphertext) - 1] = str_pad($ciphertext[count($ciphertext) - 1], $this->k, chr(0), STR_PAD_LEFT);
+
+ $plaintext = '';
+
+ switch ($this->encryptionMode) {
+ case self::ENCRYPTION_NONE:
+ $decrypt = '_raw_encrypt';
+ break;
+ case self::ENCRYPTION_PKCS1:
+ $decrypt = '_rsaes_pkcs1_v1_5_decrypt';
+ break;
+ //case self::ENCRYPTION_OAEP:
+ default:
+ $decrypt = '_rsaes_oaep_decrypt';
+ }
+
+ foreach ($ciphertext as $c) {
+ $temp = $this->$decrypt($c);
+ if ($temp === false) {
+ return false;
+ }
+ $plaintext.= $temp;
+ }
+
+ return $plaintext;
+ }
+
+ /**
+ * Create a signature
+ *
+ * @see self::verify()
+ * @access public
+ * @param string $message
+ * @return string
+ */
+ function sign($message)
+ {
+ if (empty($this->modulus) || empty($this->exponent)) {
+ return false;
+ }
+
+ switch ($this->signatureMode) {
+ case self::SIGNATURE_PKCS1:
+ return $this->_rsassa_pkcs1_v1_5_sign($message);
+ //case self::SIGNATURE_PSS:
+ default:
+ return $this->_rsassa_pss_sign($message);
+ }
+ }
+
+ /**
+ * Verifies a signature
+ *
+ * @see self::sign()
+ * @access public
+ * @param string $message
+ * @param string $signature
+ * @return bool
+ */
+ function verify($message, $signature)
+ {
+ if (empty($this->modulus) || empty($this->exponent)) {
+ return false;
+ }
+
+ switch ($this->signatureMode) {
+ case self::SIGNATURE_PKCS1:
+ return $this->_rsassa_pkcs1_v1_5_verify($message, $signature);
+ //case self::SIGNATURE_PSS:
+ default:
+ return $this->_rsassa_pss_verify($message, $signature);
+ }
+ }
+
+ /**
+ * Extract raw BER from Base64 encoding
+ *
+ * @access private
+ * @param string $str
+ * @return string
+ */
+ function _extractBER($str)
+ {
+ /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
+ * above and beyond the ceritificate.
+ * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
+ *
+ * Bag Attributes
+ * localKeyID: 01 00 00 00
+ * subject=/O=organization/OU=org unit/CN=common name
+ * issuer=/O=organization/CN=common name
+ */
+ $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
+ // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
+ $temp = preg_replace('#-+[^-]+-+#', '', $temp);
+ // remove new lines
+ $temp = str_replace(array("\r", "\n", ' '), '', $temp);
+ $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
+ return $temp != false ? $temp : $str;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Random Number Generator
+ *
+ * PHP version 5
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * echo bin2hex(\phpseclib\Crypt\Random::string(8));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package Random
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP Random Number Generator
+ *
+ * @package Random
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class Random
+{
+ /**
+ * Generate a random string.
+ *
+ * Although microoptimizations are generally discouraged as they impair readability this function is ripe with
+ * microoptimizations because this function has the potential of being called a huge number of times.
+ * eg. for RSA key generation.
+ *
+ * @param int $length
+ * @return string
+ */
+ static function string($length)
+ {
+ if (!$length) {
+ return '';
+ }
+
+ if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
+ try {
+ return \random_bytes($length);
+ } catch (\Throwable $e) {
+ // If a sufficient source of randomness is unavailable, random_bytes() will throw an
+ // object that implements the Throwable interface (Exception, TypeError, Error).
+ // We don't actually need to do anything here. The string() method should just continue
+ // as normal. Note, however, that if we don't have a sufficient source of randomness for
+ // random_bytes(), most of the other calls here will fail too, so we'll end up using
+ // the PHP implementation.
+ }
+ }
+
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
+ // ie. class_alias is a function that was introduced in PHP 5.3
+ if (extension_loaded('mcrypt') && function_exists('class_alias')) {
+ return @mcrypt_create_iv($length);
+ }
+ // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
+ // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
+ // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
+ // call php_win32_get_random_bytes():
+ //
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
+ //
+ // php_win32_get_random_bytes() is defined thusly:
+ //
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
+ //
+ // we're calling it, all the same, in the off chance that the mcrypt extension is not available
+ if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
+ return openssl_random_pseudo_bytes($length);
+ }
+ } else {
+ // method 1. the fastest
+ if (extension_loaded('openssl')) {
+ return openssl_random_pseudo_bytes($length);
+ }
+ // method 2
+ static $fp = true;
+ if ($fp === true) {
+ // warning's will be output unles the error suppression operator is used. errors such as
+ // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
+ $fp = @fopen('/dev/urandom', 'rb');
+ }
+ if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
+ return fread($fp, $length);
+ }
+ // method 3. pretty much does the same thing as method 2 per the following url:
+ // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
+ // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
+ // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
+ // restrictions or some such
+ if (extension_loaded('mcrypt')) {
+ return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
+ }
+ }
+ // at this point we have no choice but to use a pure-PHP CSPRNG
+
+ // cascade entropy across multiple PHP instances by fixing the session and collecting all
+ // environmental variables, including the previous session data and the current session
+ // data.
+ //
+ // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
+ // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
+ // PHP isn't low level to be able to use those as sources and on a web server there's not likely
+ // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
+ // however, a ton of people visiting the website. obviously you don't want to base your seeding
+ // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
+ // by the user and (2) this isn't just looking at the data sent by the current user - it's based
+ // on the data sent by all users. one user requests the page and a hash of their info is saved.
+ // another user visits the page and the serialization of their data is utilized along with the
+ // server envirnment stuff and a hash of the previous http request data (which itself utilizes
+ // a hash of the session data before that). certainly an attacker should be assumed to have
+ // full control over his own http requests. he, however, is not going to have control over
+ // everyone's http requests.
+ static $crypto = false, $v;
+ if ($crypto === false) {
+ // save old session data
+ $old_session_id = session_id();
+ $old_use_cookies = ini_get('session.use_cookies');
+ $old_session_cache_limiter = session_cache_limiter();
+ $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
+ if ($old_session_id != '') {
+ session_write_close();
+ }
+
+ session_id(1);
+ ini_set('session.use_cookies', 0);
+ session_cache_limiter('');
+ session_start();
+
+ $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
+ (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
+ (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
+ (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
+ (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
+ phpseclib_safe_serialize($GLOBALS) .
+ phpseclib_safe_serialize($_SESSION) .
+ phpseclib_safe_serialize($_OLD_SESSION)
+ ));
+ if (!isset($_SESSION['count'])) {
+ $_SESSION['count'] = 0;
+ }
+ $_SESSION['count']++;
+
+ session_write_close();
+
+ // restore old session data
+ if ($old_session_id != '') {
+ session_id($old_session_id);
+ session_start();
+ ini_set('session.use_cookies', $old_use_cookies);
+ session_cache_limiter($old_session_cache_limiter);
+ } else {
+ if ($_OLD_SESSION !== false) {
+ $_SESSION = $_OLD_SESSION;
+ unset($_OLD_SESSION);
+ } else {
+ unset($_SESSION);
+ }
+ }
+
+ // in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
+ // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
+ // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
+ // original hash and the current hash. we'll be emulating that. for more info see the following URL:
+ //
+ // http://tools.ietf.org/html/rfc4253#section-7.2
+ //
+ // see the is_string($crypto) part for an example of how to expand the keys
+ $key = pack('H*', sha1($seed . 'A'));
+ $iv = pack('H*', sha1($seed . 'C'));
+
+ // ciphers are used as per the nist.gov link below. also, see this link:
+ //
+ // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
+ switch (true) {
+ case class_exists('\phpseclib\Crypt\AES'):
+ $crypto = new AES(Base::MODE_CTR);
+ break;
+ case class_exists('\phpseclib\Crypt\Twofish'):
+ $crypto = new Twofish(Base::MODE_CTR);
+ break;
+ case class_exists('\phpseclib\Crypt\Blowfish'):
+ $crypto = new Blowfish(Base::MODE_CTR);
+ break;
+ case class_exists('\phpseclib\Crypt\TripleDES'):
+ $crypto = new TripleDES(Base::MODE_CTR);
+ break;
+ case class_exists('\phpseclib\Crypt\DES'):
+ $crypto = new DES(Base::MODE_CTR);
+ break;
+ case class_exists('\phpseclib\Crypt\RC4'):
+ $crypto = new RC4();
+ break;
+ default:
+ user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
+ return false;
+ }
+
+ $crypto->setKey($key);
+ $crypto->setIV($iv);
+ $crypto->enableContinuousBuffer();
+ }
+
+ //return $crypto->encrypt(str_repeat("\0", $length));
+
+ // the following is based off of ANSI X9.31:
+ //
+ // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
+ //
+ // OpenSSL uses that same standard for it's random numbers:
+ //
+ // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
+ // (do a search for "ANS X9.31 A.2.4")
+ $result = '';
+ while (strlen($result) < $length) {
+ $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
+ $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
+ $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
+ $result.= $r;
+ }
+ return substr($result, 0, $length);
+ }
+}
+
+if (!function_exists('phpseclib_safe_serialize')) {
+ /**
+ * Safely serialize variables
+ *
+ * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
+ * PHP 5.3 will emit a warning.
+ *
+ * @param mixed $arr
+ * @access public
+ */
+ function phpseclib_safe_serialize(&$arr)
+ {
+ if (is_object($arr)) {
+ return '';
+ }
+ if (!is_array($arr)) {
+ return serialize($arr);
+ }
+ // prevent circular array recursion
+ if (isset($arr['__phpseclib_marker'])) {
+ return '';
+ }
+ $safearr = array();
+ $arr['__phpseclib_marker'] = true;
+ foreach (array_keys($arr) as $key) {
+ // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
+ if ($key !== '__phpseclib_marker') {
+ $safearr[$key] = phpseclib_safe_serialize($arr[$key]);
+ }
+ }
+ unset($arr['__phpseclib_marker']);
+ return serialize($safearr);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of Rijndael.
+ *
+ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
+ * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
+ * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
+ * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
+ * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
+ *
+ * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
+ * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
+ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
+ * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224. Indeed, 160 and 224
+ * are first defined as valid key / block lengths in
+ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
+ * Extensions: Other block and Cipher Key lengths.
+ * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
+ *
+ * {@internal The variable names are the same as those in
+ * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $rijndael = new \phpseclib\Crypt\Rijndael();
+ *
+ * $rijndael->setKey('abcdefghijklmnop');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $rijndael->decrypt($rijndael->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package Rijndael
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2008 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of Rijndael.
+ *
+ * @package Rijndael
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class Rijndael extends Base
+{
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
+ * \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable
+ * or not for the current $block_size/$key_length.
+ * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
+ *
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @see \phpseclib\Crypt\Base::engine
+ * @see self::isValidEngine()
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'rijndael-128';
+
+ /**
+ * The default salt used by setPassword()
+ *
+ * @see \phpseclib\Crypt\Base::password_default_salt
+ * @see \phpseclib\Crypt\Base::setPassword()
+ * @var string
+ * @access private
+ */
+ var $password_default_salt = 'phpseclib';
+
+ /**
+ * The Key Schedule
+ *
+ * @see self::_setup()
+ * @var array
+ * @access private
+ */
+ var $w;
+
+ /**
+ * The Inverse Key Schedule
+ *
+ * @see self::_setup()
+ * @var array
+ * @access private
+ */
+ var $dw;
+
+ /**
+ * The Block Length divided by 32
+ *
+ * @see self::setBlockLength()
+ * @var int
+ * @access private
+ * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
+ * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
+ * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
+ * of that, we'll just precompute it once.
+ */
+ var $Nb = 4;
+
+ /**
+ * The Key Length (in bytes)
+ *
+ * @see self::setKeyLength()
+ * @var int
+ * @access private
+ * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
+ * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
+ * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
+ * of that, we'll just precompute it once.
+ */
+ var $key_length = 16;
+
+ /**
+ * The Key Length divided by 32
+ *
+ * @see self::setKeyLength()
+ * @var int
+ * @access private
+ * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
+ */
+ var $Nk = 4;
+
+ /**
+ * The Number of Rounds
+ *
+ * @var int
+ * @access private
+ * @internal The max value is 14, the min value is 10.
+ */
+ var $Nr;
+
+ /**
+ * Shift offsets
+ *
+ * @var array
+ * @access private
+ */
+ var $c;
+
+ /**
+ * Holds the last used key- and block_size information
+ *
+ * @var array
+ * @access private
+ */
+ var $kl;
+
+ /**
+ * Sets the key length.
+ *
+ * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
+ *
+ * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
+ * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
+ * 192/256 bits as, for example, mcrypt will do.
+ *
+ * That said, if you want be compatible with other Rijndael and AES implementations,
+ * you should not setKeyLength(160) or setKeyLength(224).
+ *
+ * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
+ * the mcrypt php extension, even if available.
+ * This results then in slower encryption.
+ *
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ switch (true) {
+ case $length <= 128:
+ $this->key_length = 16;
+ break;
+ case $length <= 160:
+ $this->key_length = 20;
+ break;
+ case $length <= 192:
+ $this->key_length = 24;
+ break;
+ case $length <= 224:
+ $this->key_length = 28;
+ break;
+ default:
+ $this->key_length = 32;
+ }
+
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Sets the block length
+ *
+ * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
+ * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
+ *
+ * @access public
+ * @param int $length
+ */
+ function setBlockLength($length)
+ {
+ $length >>= 5;
+ if ($length > 8) {
+ $length = 8;
+ } elseif ($length < 4) {
+ $length = 4;
+ }
+ $this->Nb = $length;
+ $this->block_size = $length << 2;
+ $this->changed = true;
+ $this->_setEngine();
+ }
+
+ /**
+ * Test for engine validity
+ *
+ * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
+ *
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ switch ($engine) {
+ case self::ENGINE_OPENSSL:
+ if ($this->block_size != 16) {
+ return false;
+ }
+ $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
+ $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
+ break;
+ case self::ENGINE_MCRYPT:
+ $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
+ if ($this->key_length % 8) { // is it a 160/224-bit key?
+ // mcrypt is not usable for them, only for 128/192/256-bit keys
+ return false;
+ }
+ }
+
+ return parent::isValidEngine($engine);
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _encryptBlock($in)
+ {
+ static $tables;
+ if (empty($tables)) {
+ $tables = &$this->_getTables();
+ }
+ $t0 = $tables[0];
+ $t1 = $tables[1];
+ $t2 = $tables[2];
+ $t3 = $tables[3];
+ $sbox = $tables[4];
+
+ $state = array();
+ $words = unpack('N*', $in);
+
+ $c = $this->c;
+ $w = $this->w;
+ $Nb = $this->Nb;
+ $Nr = $this->Nr;
+
+ // addRoundKey
+ $wc = $Nb - 1;
+ foreach ($words as $word) {
+ $state[] = $word ^ $w[++$wc];
+ }
+
+ // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
+ // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
+ // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
+ // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
+ // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
+ // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
+
+ // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
+ $temp = array();
+ for ($round = 1; $round < $Nr; ++$round) {
+ $i = 0; // $c[0] == 0
+ $j = $c[1];
+ $k = $c[2];
+ $l = $c[3];
+
+ while ($i < $Nb) {
+ $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
+ $t1[$state[$j] >> 16 & 0x000000FF] ^
+ $t2[$state[$k] >> 8 & 0x000000FF] ^
+ $t3[$state[$l] & 0x000000FF] ^
+ $w[++$wc];
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+ $state = $temp;
+ }
+
+ // subWord
+ for ($i = 0; $i < $Nb; ++$i) {
+ $state[$i] = $sbox[$state[$i] & 0x000000FF] |
+ ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) |
+ ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
+ ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
+ }
+
+ // shiftRows + addRoundKey
+ $i = 0; // $c[0] == 0
+ $j = $c[1];
+ $k = $c[2];
+ $l = $c[3];
+ while ($i < $Nb) {
+ $temp[$i] = ($state[$i] & 0xFF000000) ^
+ ($state[$j] & 0x00FF0000) ^
+ ($state[$k] & 0x0000FF00) ^
+ ($state[$l] & 0x000000FF) ^
+ $w[$i];
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+
+ switch ($Nb) {
+ case 8:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
+ case 7:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
+ case 6:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
+ case 5:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
+ default:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
+ }
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _decryptBlock($in)
+ {
+ static $invtables;
+ if (empty($invtables)) {
+ $invtables = &$this->_getInvTables();
+ }
+ $dt0 = $invtables[0];
+ $dt1 = $invtables[1];
+ $dt2 = $invtables[2];
+ $dt3 = $invtables[3];
+ $isbox = $invtables[4];
+
+ $state = array();
+ $words = unpack('N*', $in);
+
+ $c = $this->c;
+ $dw = $this->dw;
+ $Nb = $this->Nb;
+ $Nr = $this->Nr;
+
+ // addRoundKey
+ $wc = $Nb - 1;
+ foreach ($words as $word) {
+ $state[] = $word ^ $dw[++$wc];
+ }
+
+ $temp = array();
+ for ($round = $Nr - 1; $round > 0; --$round) {
+ $i = 0; // $c[0] == 0
+ $j = $Nb - $c[1];
+ $k = $Nb - $c[2];
+ $l = $Nb - $c[3];
+
+ while ($i < $Nb) {
+ $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
+ $dt1[$state[$j] >> 16 & 0x000000FF] ^
+ $dt2[$state[$k] >> 8 & 0x000000FF] ^
+ $dt3[$state[$l] & 0x000000FF] ^
+ $dw[++$wc];
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+ $state = $temp;
+ }
+
+ // invShiftRows + invSubWord + addRoundKey
+ $i = 0; // $c[0] == 0
+ $j = $Nb - $c[1];
+ $k = $Nb - $c[2];
+ $l = $Nb - $c[3];
+
+ while ($i < $Nb) {
+ $word = ($state[$i] & 0xFF000000) |
+ ($state[$j] & 0x00FF0000) |
+ ($state[$k] & 0x0000FF00) |
+ ($state[$l] & 0x000000FF);
+
+ $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] |
+ ($isbox[$word >> 8 & 0x000000FF] << 8) |
+ ($isbox[$word >> 16 & 0x000000FF] << 16) |
+ ($isbox[$word >> 24 & 0x000000FF] << 24));
+ ++$i;
+ $j = ($j + 1) % $Nb;
+ $k = ($k + 1) % $Nb;
+ $l = ($l + 1) % $Nb;
+ }
+
+ switch ($Nb) {
+ case 8:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
+ case 7:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
+ case 6:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
+ case 5:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
+ default:
+ return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
+ }
+ }
+
+ /**
+ * Setup the key (expansion)
+ *
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
+ // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
+ static $rcon = array(0,
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+ 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
+ 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
+ 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
+ 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
+ 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
+ );
+
+ if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
+ // already expanded
+ return;
+ }
+ $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
+
+ $this->Nk = $this->key_length >> 2;
+ // see Rijndael-ammended.pdf#page=44
+ $this->Nr = max($this->Nk, $this->Nb) + 6;
+
+ // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
+ // "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
+ // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
+ // "Table 2: Shift offsets for different block lengths"
+ switch ($this->Nb) {
+ case 4:
+ case 5:
+ case 6:
+ $this->c = array(0, 1, 2, 3);
+ break;
+ case 7:
+ $this->c = array(0, 1, 2, 4);
+ break;
+ case 8:
+ $this->c = array(0, 1, 3, 4);
+ }
+
+ $w = array_values(unpack('N*words', $this->key));
+
+ $length = $this->Nb * ($this->Nr + 1);
+ for ($i = $this->Nk; $i < $length; $i++) {
+ $temp = $w[$i - 1];
+ if ($i % $this->Nk == 0) {
+ // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
+ // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
+ // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
+ // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
+ $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
+ $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
+ } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
+ $temp = $this->_subWord($temp);
+ }
+ $w[$i] = $w[$i - $this->Nk] ^ $temp;
+ }
+
+ // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
+ // and generate the inverse key schedule. more specifically,
+ // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
+ // "The key expansion for the Inverse Cipher is defined as follows:
+ // 1. Apply the Key Expansion.
+ // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
+ // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
+ list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
+ $temp = $this->w = $this->dw = array();
+ for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
+ if ($col == $this->Nb) {
+ if ($row == 0) {
+ $this->dw[0] = $this->w[0];
+ } else {
+ // subWord + invMixColumn + invSubWord = invMixColumn
+ $j = 0;
+ while ($j < $this->Nb) {
+ $dw = $this->_subWord($this->w[$row][$j]);
+ $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
+ $dt1[$dw >> 16 & 0x000000FF] ^
+ $dt2[$dw >> 8 & 0x000000FF] ^
+ $dt3[$dw & 0x000000FF];
+ $j++;
+ }
+ $this->dw[$row] = $temp;
+ }
+
+ $col = 0;
+ $row++;
+ }
+ $this->w[$row][$col] = $w[$i];
+ }
+
+ $this->dw[$row] = $this->w[$row];
+
+ // Converting to 1-dim key arrays (both ascending)
+ $this->dw = array_reverse($this->dw);
+ $w = array_pop($this->w);
+ $dw = array_pop($this->dw);
+ foreach ($this->w as $r => $wr) {
+ foreach ($wr as $c => $wc) {
+ $w[] = $wc;
+ $dw[] = $this->dw[$r][$c];
+ }
+ }
+ $this->w = $w;
+ $this->dw = $dw;
+ }
+
+ /**
+ * Performs S-Box substitutions
+ *
+ * @access private
+ * @param int $word
+ */
+ function _subWord($word)
+ {
+ static $sbox;
+ if (empty($sbox)) {
+ list(, , , , $sbox) = $this->_getTables();
+ }
+
+ return $sbox[$word & 0x000000FF] |
+ ($sbox[$word >> 8 & 0x000000FF] << 8) |
+ ($sbox[$word >> 16 & 0x000000FF] << 16) |
+ ($sbox[$word >> 24 & 0x000000FF] << 24);
+ }
+
+ /**
+ * Provides the mixColumns and sboxes tables
+ *
+ * @see self::_encryptBlock()
+ * @see self::_setupInlineCrypt()
+ * @see self::_subWord()
+ * @access private
+ * @return array &$tables
+ */
+ function &_getTables()
+ {
+ static $tables;
+ if (empty($tables)) {
+ // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
+ // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
+ // those are the names we'll use.
+ $t3 = array_map('intval', array(
+ // with array_map('intval', ...) we ensure we have only int's and not
+ // some slower floats converted by php automatically on high values
+ 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
+ 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
+ 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
+ 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
+ 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
+ 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
+ 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
+ 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
+ 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
+ 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
+ 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
+ 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
+ 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
+ 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
+ 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
+ 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
+ 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
+ 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
+ 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
+ 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
+ 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
+ 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
+ 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
+ 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
+ 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
+ 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
+ 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
+ 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
+ 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
+ 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
+ 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
+ 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
+ ));
+
+ foreach ($t3 as $t3i) {
+ $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF);
+ $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
+ $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
+ }
+
+ $tables = array(
+ // The Precomputed mixColumns tables t0 - t3
+ $t0,
+ $t1,
+ $t2,
+ $t3,
+ // The SubByte S-Box
+ array(
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+ )
+ );
+ }
+ return $tables;
+ }
+
+ /**
+ * Provides the inverse mixColumns and inverse sboxes tables
+ *
+ * @see self::_decryptBlock()
+ * @see self::_setupInlineCrypt()
+ * @see self::_setupKey()
+ * @access private
+ * @return array &$tables
+ */
+ function &_getInvTables()
+ {
+ static $tables;
+ if (empty($tables)) {
+ $dt3 = array_map('intval', array(
+ 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
+ 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
+ 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
+ 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
+ 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
+ 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
+ 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
+ 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
+ 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
+ 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
+ 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
+ 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
+ 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
+ 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
+ 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
+ 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
+ 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
+ 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
+ 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
+ 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
+ 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
+ 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
+ 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
+ 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
+ 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
+ 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
+ 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
+ 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
+ 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
+ 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
+ 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
+ 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
+ ));
+
+ foreach ($dt3 as $dt3i) {
+ $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
+ $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
+ $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
+ };
+
+ $tables = array(
+ // The Precomputed inverse mixColumns tables dt0 - dt3
+ $dt0,
+ $dt1,
+ $dt2,
+ $dt3,
+ // The inverse SubByte S-Box
+ array(
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+ )
+ );
+ }
+ return $tables;
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ // Note: _setupInlineCrypt() will be called only if $this->changed === true
+ // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
+ // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
+
+ $lambda_functions =& self::_getLambdaFunctions();
+
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
+ // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
+
+ // Generation of a uniqe hash for our generated code
+ $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
+ if ($gen_hi_opt_code) {
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
+ }
+
+ if (!isset($lambda_functions[$code_hash])) {
+ switch (true) {
+ case $gen_hi_opt_code:
+ // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
+ $w = $this->w;
+ $dw = $this->dw;
+ $init_encrypt = '';
+ $init_decrypt = '';
+ break;
+ default:
+ for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
+ $w[] = '$w[' . $i . ']';
+ $dw[] = '$dw[' . $i . ']';
+ }
+ $init_encrypt = '$w = $self->w;';
+ $init_decrypt = '$dw = $self->dw;';
+ }
+
+ $Nr = $this->Nr;
+ $Nb = $this->Nb;
+ $c = $this->c;
+
+ // Generating encrypt code:
+ $init_encrypt.= '
+ static $tables;
+ if (empty($tables)) {
+ $tables = &$self->_getTables();
+ }
+ $t0 = $tables[0];
+ $t1 = $tables[1];
+ $t2 = $tables[2];
+ $t3 = $tables[3];
+ $sbox = $tables[4];
+ ';
+
+ $s = 'e';
+ $e = 's';
+ $wc = $Nb - 1;
+
+ // Preround: addRoundKey
+ $encrypt_block = '$in = unpack("N*", $in);'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
+ }
+
+ // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
+ for ($round = 1; $round < $Nr; ++$round) {
+ list($s, $e) = array($e, $s);
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block.=
+ '$'.$e.$i.' =
+ $t0[($'.$s.$i .' >> 24) & 0xff] ^
+ $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
+ $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^
+ $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^
+ '.$w[++$wc].";\n";
+ }
+ }
+
+ // Finalround: subWord + shiftRows + addRoundKey
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block.=
+ '$'.$e.$i.' =
+ $sbox[ $'.$e.$i.' & 0xff] |
+ ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
+ ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
+ ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
+ }
+ $encrypt_block .= '$in = pack("N*"'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $encrypt_block.= ',
+ ($'.$e.$i .' & '.((int)0xFF000000).') ^
+ ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
+ ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
+ ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
+ '.$w[$i]."\n";
+ }
+ $encrypt_block .= ');';
+
+ // Generating decrypt code:
+ $init_decrypt.= '
+ static $invtables;
+ if (empty($invtables)) {
+ $invtables = &$self->_getInvTables();
+ }
+ $dt0 = $invtables[0];
+ $dt1 = $invtables[1];
+ $dt2 = $invtables[2];
+ $dt3 = $invtables[3];
+ $isbox = $invtables[4];
+ ';
+
+ $s = 'e';
+ $e = 's';
+ $wc = $Nb - 1;
+
+ // Preround: addRoundKey
+ $decrypt_block = '$in = unpack("N*", $in);'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
+ }
+
+ // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
+ for ($round = 1; $round < $Nr; ++$round) {
+ list($s, $e) = array($e, $s);
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block.=
+ '$'.$e.$i.' =
+ $dt0[($'.$s.$i .' >> 24) & 0xff] ^
+ $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
+ $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^
+ $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^
+ '.$dw[++$wc].";\n";
+ }
+ }
+
+ // Finalround: subWord + shiftRows + addRoundKey
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block.=
+ '$'.$e.$i.' =
+ $isbox[ $'.$e.$i.' & 0xff] |
+ ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
+ ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
+ ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
+ }
+ $decrypt_block .= '$in = pack("N*"'."\n";
+ for ($i = 0; $i < $Nb; ++$i) {
+ $decrypt_block.= ',
+ ($'.$e.$i. ' & '.((int)0xFF000000).') ^
+ ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
+ ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
+ ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
+ '.$dw[$i]."\n";
+ }
+ $decrypt_block .= ');';
+
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
+ array(
+ 'init_crypt' => '',
+ 'init_encrypt' => $init_encrypt,
+ 'init_decrypt' => $init_decrypt,
+ 'encrypt_block' => $encrypt_block,
+ 'decrypt_block' => $decrypt_block
+ )
+ );
+ }
+ $this->inline_crypt = $lambda_functions[$code_hash];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of Triple DES.
+ *
+ * Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
+ *
+ * PHP version 5
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $des = new \phpseclib\Crypt\TripleDES();
+ *
+ * $des->setKey('abcdefghijklmnopqrstuvwx');
+ *
+ * $size = 10 * 1024;
+ * $plaintext = '';
+ * for ($i = 0; $i < $size; $i++) {
+ * $plaintext.= 'a';
+ * }
+ *
+ * echo $des->decrypt($des->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package TripleDES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of Triple DES.
+ *
+ * @package TripleDES
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class TripleDES extends DES
+{
+ /**
+ * Encrypt / decrypt using inner chaining
+ *
+ * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
+ */
+ const MODE_3CBC = -2;
+
+ /**
+ * Encrypt / decrypt using outer chaining
+ *
+ * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC.
+ */
+ const MODE_CBC3 = Base::MODE_CBC;
+
+ /**
+ * Key Length (in bytes)
+ *
+ * @see \phpseclib\Crypt\TripleDES::setKeyLength()
+ * @var int
+ * @access private
+ */
+ var $key_length = 24;
+
+ /**
+ * The default salt used by setPassword()
+ *
+ * @see \phpseclib\Crypt\Base::password_default_salt
+ * @see \phpseclib\Crypt\Base::setPassword()
+ * @var string
+ * @access private
+ */
+ var $password_default_salt = 'phpseclib';
+
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * @see \phpseclib\Crypt\DES::cipher_name_mcrypt
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'tripledes';
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * @see \phpseclib\Crypt\Base::cfb_init_len
+ * @var int
+ * @access private
+ */
+ var $cfb_init_len = 750;
+
+ /**
+ * max possible size of $key
+ *
+ * @see self::setKey()
+ * @see \phpseclib\Crypt\DES::setKey()
+ * @var string
+ * @access private
+ */
+ var $key_length_max = 24;
+
+ /**
+ * Internal flag whether using self::MODE_3CBC or not
+ *
+ * @var bool
+ * @access private
+ */
+ var $mode_3cbc;
+
+ /**
+ * The \phpseclib\Crypt\DES objects
+ *
+ * Used only if $mode_3cbc === true
+ *
+ * @var array
+ * @access private
+ */
+ var $des;
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * $mode could be:
+ *
+ * - \phpseclib\Crypt\Base::MODE_ECB
+ *
+ * - \phpseclib\Crypt\Base::MODE_CBC
+ *
+ * - \phpseclib\Crypt\Base::MODE_CTR
+ *
+ * - \phpseclib\Crypt\Base::MODE_CFB
+ *
+ * - \phpseclib\Crypt\Base::MODE_OFB
+ *
+ * - \phpseclib\Crypt\TripleDES::MODE_3CBC
+ *
+ * If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
+ *
+ * @see \phpseclib\Crypt\DES::__construct()
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @param int $mode
+ * @access public
+ */
+ function __construct($mode = Base::MODE_CBC)
+ {
+ switch ($mode) {
+ // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
+ // and additional flag us internally as 3CBC
+ case self::MODE_3CBC:
+ parent::__construct(Base::MODE_CBC);
+ $this->mode_3cbc = true;
+
+ // This three $des'es will do the 3CBC work (if $key > 64bits)
+ $this->des = array(
+ new DES(Base::MODE_CBC),
+ new DES(Base::MODE_CBC),
+ new DES(Base::MODE_CBC),
+ );
+
+ // we're going to be doing the padding, ourselves, so disable it in the \phpseclib\Crypt\DES objects
+ $this->des[0]->disablePadding();
+ $this->des[1]->disablePadding();
+ $this->des[2]->disablePadding();
+ break;
+ // If not 3CBC, we init as usual
+ default:
+ parent::__construct($mode);
+ }
+ }
+
+ /**
+ * Test for engine validity
+ *
+ * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
+ *
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ function isValidEngine($engine)
+ {
+ if ($engine == self::ENGINE_OPENSSL) {
+ $this->cipher_name_openssl_ecb = 'des-ede3';
+ $mode = $this->_openssl_translate_mode();
+ $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
+ }
+
+ return parent::isValidEngine($engine);
+ }
+
+ /**
+ * Sets the initialization vector. (optional)
+ *
+ * SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed
+ * to be all zero's.
+ *
+ * @see \phpseclib\Crypt\Base::setIV()
+ * @access public
+ * @param string $iv
+ */
+ function setIV($iv)
+ {
+ parent::setIV($iv);
+ if ($this->mode_3cbc) {
+ $this->des[0]->setIV($iv);
+ $this->des[1]->setIV($iv);
+ $this->des[2]->setIV($iv);
+ }
+ }
+
+ /**
+ * Sets the key length.
+ *
+ * Valid key lengths are 64, 128 and 192
+ *
+ * @see \phpseclib\Crypt\Base:setKeyLength()
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ $length >>= 3;
+ switch (true) {
+ case $length <= 8:
+ $this->key_length = 8;
+ break;
+ case $length <= 16:
+ $this->key_length = 16;
+ break;
+ default:
+ $this->key_length = 24;
+ }
+
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Sets the key.
+ *
+ * Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
+ * 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
+ *
+ * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
+ *
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
+ *
+ * @access public
+ * @see \phpseclib\Crypt\DES::setKey()
+ * @see \phpseclib\Crypt\Base::setKey()
+ * @param string $key
+ */
+ function setKey($key)
+ {
+ $length = $this->explicit_key_length ? $this->key_length : strlen($key);
+ if ($length > 8) {
+ $key = str_pad(substr($key, 0, 24), 24, chr(0));
+ // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
+ // http://php.net/function.mcrypt-encrypt#47973
+ $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
+ } else {
+ $key = str_pad($key, 8, chr(0));
+ }
+ parent::setKey($key);
+
+ // And in case of self::MODE_3CBC:
+ // if key <= 64bits we not need the 3 $des to work,
+ // because we will then act as regular DES-CBC with just a <= 64bit key.
+ // So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
+ if ($this->mode_3cbc && $length > 8) {
+ $this->des[0]->setKey(substr($key, 0, 8));
+ $this->des[1]->setKey(substr($key, 8, 8));
+ $this->des[2]->setKey(substr($key, 16, 8));
+ }
+ }
+
+ /**
+ * Encrypts a message.
+ *
+ * @see \phpseclib\Crypt\Base::encrypt()
+ * @access public
+ * @param string $plaintext
+ * @return string $cipertext
+ */
+ function encrypt($plaintext)
+ {
+ // parent::en/decrypt() is able to do all the work for all modes and keylengths,
+ // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
+
+ // if the key is smaller then 8, do what we'd normally do
+ if ($this->mode_3cbc && strlen($this->key) > 8) {
+ return $this->des[2]->encrypt(
+ $this->des[1]->decrypt(
+ $this->des[0]->encrypt(
+ $this->_pad($plaintext)
+ )
+ )
+ );
+ }
+
+ return parent::encrypt($plaintext);
+ }
+
+ /**
+ * Decrypts a message.
+ *
+ * @see \phpseclib\Crypt\Base::decrypt()
+ * @access public
+ * @param string $ciphertext
+ * @return string $plaintext
+ */
+ function decrypt($ciphertext)
+ {
+ if ($this->mode_3cbc && strlen($this->key) > 8) {
+ return $this->_unpad(
+ $this->des[0]->decrypt(
+ $this->des[1]->encrypt(
+ $this->des[2]->decrypt(
+ str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
+ )
+ )
+ )
+ );
+ }
+
+ return parent::decrypt($ciphertext);
+ }
+
+ /**
+ * Treat consecutive "packets" as if they are a continuous buffer.
+ *
+ * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
+ * will yield different outputs:
+ *
+ * <code>
+ * echo $des->encrypt(substr($plaintext, 0, 8));
+ * echo $des->encrypt(substr($plaintext, 8, 8));
+ * </code>
+ * <code>
+ * echo $des->encrypt($plaintext);
+ * </code>
+ *
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
+ * another, as demonstrated with the following:
+ *
+ * <code>
+ * $des->encrypt(substr($plaintext, 0, 8));
+ * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
+ * </code>
+ * <code>
+ * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
+ * </code>
+ *
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
+ *
+ * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\DES() object changes after each
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
+ * however, they are also less intuitive and more likely to cause you problems.
+ *
+ * @see \phpseclib\Crypt\Base::enableContinuousBuffer()
+ * @see self::disableContinuousBuffer()
+ * @access public
+ */
+ function enableContinuousBuffer()
+ {
+ parent::enableContinuousBuffer();
+ if ($this->mode_3cbc) {
+ $this->des[0]->enableContinuousBuffer();
+ $this->des[1]->enableContinuousBuffer();
+ $this->des[2]->enableContinuousBuffer();
+ }
+ }
+
+ /**
+ * Treat consecutive packets as if they are a discontinuous buffer.
+ *
+ * The default behavior.
+ *
+ * @see \phpseclib\Crypt\Base::disableContinuousBuffer()
+ * @see self::enableContinuousBuffer()
+ * @access public
+ */
+ function disableContinuousBuffer()
+ {
+ parent::disableContinuousBuffer();
+ if ($this->mode_3cbc) {
+ $this->des[0]->disableContinuousBuffer();
+ $this->des[1]->disableContinuousBuffer();
+ $this->des[2]->disableContinuousBuffer();
+ }
+ }
+
+ /**
+ * Creates the key schedule
+ *
+ * @see \phpseclib\Crypt\DES::_setupKey()
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ switch (true) {
+ // if $key <= 64bits we configure our internal pure-php cipher engine
+ // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
+ case strlen($this->key) <= 8:
+ $this->des_rounds = 1;
+ break;
+
+ // otherwise, if $key > 64bits, we configure our engine to work as 3DES.
+ default:
+ $this->des_rounds = 3;
+
+ // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
+ if ($this->mode_3cbc) {
+ $this->des[0]->_setupKey();
+ $this->des[1]->_setupKey();
+ $this->des[2]->_setupKey();
+
+ // because $des[0-2] will, now, do all the work we can return here
+ // not need unnecessary stress parent::_setupKey() with our, now unused, $key.
+ return;
+ }
+ }
+ // setup our key
+ parent::_setupKey();
+ }
+
+ /**
+ * Sets the internal crypt engine
+ *
+ * @see \phpseclib\Crypt\Base::__construct()
+ * @see \phpseclib\Crypt\Base::setPreferredEngine()
+ * @param int $engine
+ * @access public
+ * @return int
+ */
+ function setPreferredEngine($engine)
+ {
+ if ($this->mode_3cbc) {
+ $this->des[0]->setPreferredEngine($engine);
+ $this->des[1]->setPreferredEngine($engine);
+ $this->des[2]->setPreferredEngine($engine);
+ }
+
+ return parent::setPreferredEngine($engine);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of Twofish.
+ *
+ * Uses mcrypt, if available, and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $twofish = new \phpseclib\Crypt\Twofish();
+ *
+ * $twofish->setKey('12345678901234567890123456789012');
+ *
+ * $plaintext = str_repeat('a', 1024);
+ *
+ * echo $twofish->decrypt($twofish->encrypt($plaintext));
+ * ?>
+ * </code>
+ *
+ * @category Crypt
+ * @package Twofish
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+/**
+ * Pure-PHP implementation of Twofish.
+ *
+ * @package Twofish
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @access public
+ */
+class Twofish extends Base
+{
+ /**
+ * The mcrypt specific name of the cipher
+ *
+ * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
+ * @var string
+ * @access private
+ */
+ var $cipher_name_mcrypt = 'twofish';
+
+ /**
+ * Optimizing value while CFB-encrypting
+ *
+ * @see \phpseclib\Crypt\Base::cfb_init_len
+ * @var int
+ * @access private
+ */
+ var $cfb_init_len = 800;
+
+ /**
+ * Q-Table
+ *
+ * @var array
+ * @access private
+ */
+ var $q0 = array(
+ 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
+ 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
+ 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
+ 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
+ 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
+ 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
+ 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
+ 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
+ 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
+ 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
+ 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
+ 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
+ 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
+ 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
+ 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
+ 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
+ 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
+ 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
+ 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
+ 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
+ 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
+ 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
+ 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
+ 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
+ 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
+ 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
+ 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
+ );
+
+ /**
+ * Q-Table
+ *
+ * @var array
+ * @access private
+ */
+ var $q1 = array(
+ 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
+ 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
+ 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
+ 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
+ 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
+ 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
+ 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
+ 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
+ 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
+ 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
+ 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
+ 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
+ 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
+ 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
+ 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
+ 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
+ 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
+ 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
+ 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
+ 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
+ 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
+ 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
+ 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
+ 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
+ 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
+ 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
+ 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
+ );
+
+ /**
+ * M-Table
+ *
+ * @var array
+ * @access private
+ */
+ var $m0 = array(
+ 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
+ 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
+ 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
+ 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
+ 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
+ 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
+ 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
+ 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
+ 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
+ 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
+ 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
+ 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
+ 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
+ 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
+ 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
+ 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
+ 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
+ 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
+ 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
+ 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
+ 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
+ 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
+ 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
+ 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
+ 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
+ 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
+ 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
+ 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
+ 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
+ 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
+ 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
+ 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
+ );
+
+ /**
+ * M-Table
+ *
+ * @var array
+ * @access private
+ */
+ var $m1 = array(
+ 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
+ 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
+ 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
+ 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
+ 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
+ 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
+ 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
+ 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
+ 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
+ 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
+ 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
+ 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
+ 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
+ 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
+ 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
+ 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
+ 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
+ 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
+ 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
+ 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
+ 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
+ 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
+ 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
+ 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
+ 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
+ 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
+ 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
+ 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
+ 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
+ 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
+ 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
+ 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
+ );
+
+ /**
+ * M-Table
+ *
+ * @var array
+ * @access private
+ */
+ var $m2 = array(
+ 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
+ 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
+ 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
+ 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
+ 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
+ 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
+ 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
+ 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
+ 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
+ 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
+ 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
+ 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
+ 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
+ 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
+ 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
+ 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
+ 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
+ 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
+ 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
+ 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
+ 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
+ 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
+ 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
+ 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
+ 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
+ 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
+ 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
+ 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
+ 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
+ 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
+ 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
+ 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
+ );
+
+ /**
+ * M-Table
+ *
+ * @var array
+ * @access private
+ */
+ var $m3 = array(
+ 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
+ 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
+ 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
+ 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
+ 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
+ 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
+ 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
+ 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
+ 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
+ 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
+ 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
+ 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
+ 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
+ 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
+ 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
+ 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
+ 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
+ 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
+ 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
+ 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
+ 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
+ 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
+ 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
+ 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
+ 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
+ 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
+ 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
+ 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
+ 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
+ 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
+ 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
+ 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
+ );
+
+ /**
+ * The Key Schedule Array
+ *
+ * @var array
+ * @access private
+ */
+ var $K = array();
+
+ /**
+ * The Key depended S-Table 0
+ *
+ * @var array
+ * @access private
+ */
+ var $S0 = array();
+
+ /**
+ * The Key depended S-Table 1
+ *
+ * @var array
+ * @access private
+ */
+ var $S1 = array();
+
+ /**
+ * The Key depended S-Table 2
+ *
+ * @var array
+ * @access private
+ */
+ var $S2 = array();
+
+ /**
+ * The Key depended S-Table 3
+ *
+ * @var array
+ * @access private
+ */
+ var $S3 = array();
+
+ /**
+ * Holds the last used key
+ *
+ * @var array
+ * @access private
+ */
+ var $kl;
+
+ /**
+ * The Key Length (in bytes)
+ *
+ * @see Crypt_Twofish::setKeyLength()
+ * @var int
+ * @access private
+ */
+ var $key_length = 16;
+
+ /**
+ * Sets the key length.
+ *
+ * Valid key lengths are 128, 192 or 256 bits
+ *
+ * @access public
+ * @param int $length
+ */
+ function setKeyLength($length)
+ {
+ switch (true) {
+ case $length <= 128:
+ $this->key_length = 16;
+ break;
+ case $length <= 192:
+ $this->key_length = 24;
+ break;
+ default:
+ $this->key_length = 32;
+ }
+
+ parent::setKeyLength($length);
+ }
+
+ /**
+ * Setup the key (expansion)
+ *
+ * @see \phpseclib\Crypt\Base::_setupKey()
+ * @access private
+ */
+ function _setupKey()
+ {
+ if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
+ // already expanded
+ return;
+ }
+ $this->kl = array('key' => $this->key);
+
+ /* Key expanding and generating the key-depended s-boxes */
+ $le_longs = unpack('V*', $this->key);
+ $key = unpack('C*', $this->key);
+ $m0 = $this->m0;
+ $m1 = $this->m1;
+ $m2 = $this->m2;
+ $m3 = $this->m3;
+ $q0 = $this->q0;
+ $q1 = $this->q1;
+
+ $K = $S0 = $S1 = $S2 = $S3 = array();
+
+ switch (strlen($this->key)) {
+ case 16:
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
+ $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
+ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
+ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
+ $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
+ $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
+ $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
+ $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
+ $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
+ $B = ($B << 8) | ($B >> 24 & 0xff);
+ $A = $this->safe_intval($A + $B);
+ $K[] = $A;
+ $A = $this->safe_intval($A + $B);
+ $K[] = ($A << 9 | $A >> 23 & 0x1ff);
+ }
+ for ($i = 0; $i < 256; ++$i) {
+ $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
+ $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
+ $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
+ $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
+ }
+ break;
+ case 24:
+ list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
+ $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
+ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
+ $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
+ $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
+ $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
+ $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
+ $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
+ $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
+ $B = ($B << 8) | ($B >> 24 & 0xff);
+ $A = $this->safe_intval($A + $B);
+ $K[] = $A;
+ $A = $this->safe_intval($A + $B);
+ $K[] = ($A << 9 | $A >> 23 & 0x1ff);
+ }
+ for ($i = 0; $i < 256; ++$i) {
+ $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
+ $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
+ $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
+ $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
+ }
+ break;
+ default: // 32
+ list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
+ list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
+ $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
+ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
+ $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
+ $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
+ $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
+ $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
+ $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
+ $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
+ $B = ($B << 8) | ($B >> 24 & 0xff);
+ $A = $this->safe_intval($A + $B);
+ $K[] = $A;
+ $A = $this->safe_intval($A + $B);
+ $K[] = ($A << 9 | $A >> 23 & 0x1ff);
+ }
+ for ($i = 0; $i < 256; ++$i) {
+ $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
+ $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
+ $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
+ $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
+ }
+ }
+
+ $this->K = $K;
+ $this->S0 = $S0;
+ $this->S1 = $S1;
+ $this->S2 = $S2;
+ $this->S3 = $S3;
+ }
+
+ /**
+ * _mdsrem function using by the twofish cipher algorithm
+ *
+ * @access private
+ * @param string $A
+ * @param string $B
+ * @return array
+ */
+ function _mdsrem($A, $B)
+ {
+ // No gain by unrolling this loop.
+ for ($i = 0; $i < 8; ++$i) {
+ // Get most significant coefficient.
+ $t = 0xff & ($B >> 24);
+
+ // Shift the others up.
+ $B = ($B << 8) | (0xff & ($A >> 24));
+ $A<<= 8;
+
+ $u = $t << 1;
+
+ // Subtract the modular polynomial on overflow.
+ if ($t & 0x80) {
+ $u^= 0x14d;
+ }
+
+ // Remove t * (a * x^2 + 1).
+ $B ^= $t ^ ($u << 16);
+
+ // Form u = a*t + t/a = t*(a + 1/a).
+ $u^= 0x7fffffff & ($t >> 1);
+
+ // Add the modular polynomial on underflow.
+ if ($t & 0x01) {
+ $u^= 0xa6 ;
+ }
+
+ // Remove t * (a + 1/a) * (x^3 + x).
+ $B^= ($u << 24) | ($u << 8);
+ }
+
+ return array(
+ 0xff & $B >> 24,
+ 0xff & $B >> 16,
+ 0xff & $B >> 8,
+ 0xff & $B);
+ }
+
+ /**
+ * Encrypts a block
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _encryptBlock($in)
+ {
+ $S0 = $this->S0;
+ $S1 = $this->S1;
+ $S2 = $this->S2;
+ $S3 = $this->S3;
+ $K = $this->K;
+
+ $in = unpack("V4", $in);
+ $R0 = $K[0] ^ $in[1];
+ $R1 = $K[1] ^ $in[2];
+ $R2 = $K[2] ^ $in[3];
+ $R3 = $K[3] ^ $in[4];
+
+ $ki = 7;
+ while ($ki < 39) {
+ $t0 = $S0[ $R0 & 0xff] ^
+ $S1[($R0 >> 8) & 0xff] ^
+ $S2[($R0 >> 16) & 0xff] ^
+ $S3[($R0 >> 24) & 0xff];
+ $t1 = $S0[($R1 >> 24) & 0xff] ^
+ $S1[ $R1 & 0xff] ^
+ $S2[($R1 >> 8) & 0xff] ^
+ $S3[($R1 >> 16) & 0xff];
+ $R2^= $this->safe_intval($t0 + $t1 + $K[++$ki]);
+ $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
+ $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ $this->safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
+
+ $t0 = $S0[ $R2 & 0xff] ^
+ $S1[($R2 >> 8) & 0xff] ^
+ $S2[($R2 >> 16) & 0xff] ^
+ $S3[($R2 >> 24) & 0xff];
+ $t1 = $S0[($R3 >> 24) & 0xff] ^
+ $S1[ $R3 & 0xff] ^
+ $S2[($R3 >> 8) & 0xff] ^
+ $S3[($R3 >> 16) & 0xff];
+ $R0^= $this->safe_intval($t0 + $t1 + $K[++$ki]);
+ $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
+ $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ $this->safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
+ }
+
+ // @codingStandardsIgnoreStart
+ return pack("V4", $K[4] ^ $R2,
+ $K[5] ^ $R3,
+ $K[6] ^ $R0,
+ $K[7] ^ $R1);
+ // @codingStandardsIgnoreEnd
+ }
+
+ /**
+ * Decrypts a block
+ *
+ * @access private
+ * @param string $in
+ * @return string
+ */
+ function _decryptBlock($in)
+ {
+ $S0 = $this->S0;
+ $S1 = $this->S1;
+ $S2 = $this->S2;
+ $S3 = $this->S3;
+ $K = $this->K;
+
+ $in = unpack("V4", $in);
+ $R0 = $K[4] ^ $in[1];
+ $R1 = $K[5] ^ $in[2];
+ $R2 = $K[6] ^ $in[3];
+ $R3 = $K[7] ^ $in[4];
+
+ $ki = 40;
+ while ($ki > 8) {
+ $t0 = $S0[$R0 & 0xff] ^
+ $S1[$R0 >> 8 & 0xff] ^
+ $S2[$R0 >> 16 & 0xff] ^
+ $S3[$R0 >> 24 & 0xff];
+ $t1 = $S0[$R1 >> 24 & 0xff] ^
+ $S1[$R1 & 0xff] ^
+ $S2[$R1 >> 8 & 0xff] ^
+ $S3[$R1 >> 16 & 0xff];
+ $R3^= $this->safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
+ $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
+ $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ $this->safe_intval($t0 + $t1 + $K[--$ki]);
+
+ $t0 = $S0[$R2 & 0xff] ^
+ $S1[$R2 >> 8 & 0xff] ^
+ $S2[$R2 >> 16 & 0xff] ^
+ $S3[$R2 >> 24 & 0xff];
+ $t1 = $S0[$R3 >> 24 & 0xff] ^
+ $S1[$R3 & 0xff] ^
+ $S2[$R3 >> 8 & 0xff] ^
+ $S3[$R3 >> 16 & 0xff];
+ $R1^= $this->safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
+ $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
+ $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ $this->safe_intval($t0 + $t1 + $K[--$ki]);
+ }
+
+ // @codingStandardsIgnoreStart
+ return pack("V4", $K[0] ^ $R2,
+ $K[1] ^ $R3,
+ $K[2] ^ $R0,
+ $K[3] ^ $R1);
+ // @codingStandardsIgnoreEnd
+ }
+
+ /**
+ * Setup the performance-optimized function for de/encrypt()
+ *
+ * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
+ * @access private
+ */
+ function _setupInlineCrypt()
+ {
+ $lambda_functions =& self::_getLambdaFunctions();
+
+ // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
+ // (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
+
+ // Generation of a unique hash for our generated code
+ $code_hash = "Crypt_Twofish, {$this->mode}";
+ if ($gen_hi_opt_code) {
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
+ }
+
+ $safeint = $this->safe_intval_inline();
+
+ if (!isset($lambda_functions[$code_hash])) {
+ switch (true) {
+ case $gen_hi_opt_code:
+ $K = $this->K;
+ $init_crypt = '
+ static $S0, $S1, $S2, $S3;
+ if (!$S0) {
+ for ($i = 0; $i < 256; ++$i) {
+ $S0[] = (int)$self->S0[$i];
+ $S1[] = (int)$self->S1[$i];
+ $S2[] = (int)$self->S2[$i];
+ $S3[] = (int)$self->S3[$i];
+ }
+ }
+ ';
+ break;
+ default:
+ $K = array();
+ for ($i = 0; $i < 40; ++$i) {
+ $K[] = '$K_' . $i;
+ }
+ $init_crypt = '
+ $S0 = $self->S0;
+ $S1 = $self->S1;
+ $S2 = $self->S2;
+ $S3 = $self->S3;
+ list(' . implode(',', $K) . ') = $self->K;
+ ';
+ }
+
+ // Generating encrypt code:
+ $encrypt_block = '
+ $in = unpack("V4", $in);
+ $R0 = '.$K[0].' ^ $in[1];
+ $R1 = '.$K[1].' ^ $in[2];
+ $R2 = '.$K[2].' ^ $in[3];
+ $R3 = '.$K[3].' ^ $in[4];
+ ';
+ for ($ki = 7, $i = 0; $i < 8; ++$i) {
+ $encrypt_block.= '
+ $t0 = $S0[ $R0 & 0xff] ^
+ $S1[($R0 >> 8) & 0xff] ^
+ $S2[($R0 >> 16) & 0xff] ^
+ $S3[($R0 >> 24) & 0xff];
+ $t1 = $S0[($R1 >> 24) & 0xff] ^
+ $S1[ $R1 & 0xff] ^
+ $S2[($R1 >> 8) & 0xff] ^
+ $S3[($R1 >> 16) & 0xff];
+ $R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . ';
+ $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
+ $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
+
+ $t0 = $S0[ $R2 & 0xff] ^
+ $S1[($R2 >> 8) & 0xff] ^
+ $S2[($R2 >> 16) & 0xff] ^
+ $S3[($R2 >> 24) & 0xff];
+ $t1 = $S0[($R3 >> 24) & 0xff] ^
+ $S1[ $R3 & 0xff] ^
+ $S2[($R3 >> 8) & 0xff] ^
+ $S3[($R3 >> 16) & 0xff];
+ $R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . ';
+ $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
+ $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
+ ';
+ }
+ $encrypt_block.= '
+ $in = pack("V4", ' . $K[4] . ' ^ $R2,
+ ' . $K[5] . ' ^ $R3,
+ ' . $K[6] . ' ^ $R0,
+ ' . $K[7] . ' ^ $R1);
+ ';
+
+ // Generating decrypt code:
+ $decrypt_block = '
+ $in = unpack("V4", $in);
+ $R0 = '.$K[4].' ^ $in[1];
+ $R1 = '.$K[5].' ^ $in[2];
+ $R2 = '.$K[6].' ^ $in[3];
+ $R3 = '.$K[7].' ^ $in[4];
+ ';
+ for ($ki = 40, $i = 0; $i < 8; ++$i) {
+ $decrypt_block.= '
+ $t0 = $S0[$R0 & 0xff] ^
+ $S1[$R0 >> 8 & 0xff] ^
+ $S2[$R0 >> 16 & 0xff] ^
+ $S3[$R0 >> 24 & 0xff];
+ $t1 = $S0[$R1 >> 24 & 0xff] ^
+ $S1[$R1 & 0xff] ^
+ $S2[$R1 >> 8 & 0xff] ^
+ $S3[$R1 >> 16 & 0xff];
+ $R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
+ $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
+ $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + '.$K[--$ki] . ')') . ';
+
+ $t0 = $S0[$R2 & 0xff] ^
+ $S1[$R2 >> 8 & 0xff] ^
+ $S2[$R2 >> 16 & 0xff] ^
+ $S3[$R2 >> 24 & 0xff];
+ $t1 = $S0[$R3 >> 24 & 0xff] ^
+ $S1[$R3 & 0xff] ^
+ $S2[$R3 >> 8 & 0xff] ^
+ $S3[$R3 >> 16 & 0xff];
+ $R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
+ $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
+ $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + '.$K[--$ki] . ')') . ';
+ ';
+ }
+ $decrypt_block.= '
+ $in = pack("V4", ' . $K[0] . ' ^ $R2,
+ ' . $K[1] . ' ^ $R3,
+ ' . $K[2] . ' ^ $R0,
+ ' . $K[3] . ' ^ $R1);
+ ';
+
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
+ array(
+ 'init_crypt' => $init_crypt,
+ 'init_encrypt' => '',
+ 'init_decrypt' => '',
+ 'encrypt_block' => $encrypt_block,
+ 'decrypt_block' => $decrypt_block
+ )
+ );
+ }
+ $this->inline_crypt = $lambda_functions[$code_hash];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP ANSI Decoder
+ *
+ * PHP version 5
+ *
+ * If you call read() in \phpseclib\Net\SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
+ * They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC). They tell a
+ * {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
+ * color to display them in, etc. \phpseclib\File\ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
+ *
+ * @category File
+ * @package ANSI
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2012 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\File;
+
+/**
+ * Pure-PHP ANSI Decoder
+ *
+ * @package ANSI
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class ANSI
+{
+ /**
+ * Max Width
+ *
+ * @var int
+ * @access private
+ */
+ var $max_x;
+
+ /**
+ * Max Height
+ *
+ * @var int
+ * @access private
+ */
+ var $max_y;
+
+ /**
+ * Max History
+ *
+ * @var int
+ * @access private
+ */
+ var $max_history;
+
+ /**
+ * History
+ *
+ * @var array
+ * @access private
+ */
+ var $history;
+
+ /**
+ * History Attributes
+ *
+ * @var array
+ * @access private
+ */
+ var $history_attrs;
+
+ /**
+ * Current Column
+ *
+ * @var int
+ * @access private
+ */
+ var $x;
+
+ /**
+ * Current Row
+ *
+ * @var int
+ * @access private
+ */
+ var $y;
+
+ /**
+ * Old Column
+ *
+ * @var int
+ * @access private
+ */
+ var $old_x;
+
+ /**
+ * Old Row
+ *
+ * @var int
+ * @access private
+ */
+ var $old_y;
+
+ /**
+ * An empty attribute cell
+ *
+ * @var object
+ * @access private
+ */
+ var $base_attr_cell;
+
+ /**
+ * The current attribute cell
+ *
+ * @var object
+ * @access private
+ */
+ var $attr_cell;
+
+ /**
+ * An empty attribute row
+ *
+ * @var array
+ * @access private
+ */
+ var $attr_row;
+
+ /**
+ * The current screen text
+ *
+ * @var array
+ * @access private
+ */
+ var $screen;
+
+ /**
+ * The current screen attributes
+ *
+ * @var array
+ * @access private
+ */
+ var $attrs;
+
+ /**
+ * Current ANSI code
+ *
+ * @var string
+ * @access private
+ */
+ var $ansi;
+
+ /**
+ * Tokenization
+ *
+ * @var array
+ * @access private
+ */
+ var $tokenization;
+
+ /**
+ * Default Constructor.
+ *
+ * @return \phpseclib\File\ANSI
+ * @access public
+ */
+ function __construct()
+ {
+ $attr_cell = new \stdClass();
+ $attr_cell->bold = false;
+ $attr_cell->underline = false;
+ $attr_cell->blink = false;
+ $attr_cell->background = 'black';
+ $attr_cell->foreground = 'white';
+ $attr_cell->reverse = false;
+ $this->base_attr_cell = clone $attr_cell;
+ $this->attr_cell = clone $attr_cell;
+
+ $this->setHistory(200);
+ $this->setDimensions(80, 24);
+ }
+
+ /**
+ * Set terminal width and height
+ *
+ * Resets the screen as well
+ *
+ * @param int $x
+ * @param int $y
+ * @access public
+ */
+ function setDimensions($x, $y)
+ {
+ $this->max_x = $x - 1;
+ $this->max_y = $y - 1;
+ $this->x = $this->y = 0;
+ $this->history = $this->history_attrs = array();
+ $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
+ $this->screen = array_fill(0, $this->max_y + 1, '');
+ $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
+ $this->ansi = '';
+ }
+
+ /**
+ * Set the number of lines that should be logged past the terminal height
+ *
+ * @param int $x
+ * @param int $y
+ * @access public
+ */
+ function setHistory($history)
+ {
+ $this->max_history = $history;
+ }
+
+ /**
+ * Load a string
+ *
+ * @param string $source
+ * @access public
+ */
+ function loadString($source)
+ {
+ $this->setDimensions($this->max_x + 1, $this->max_y + 1);
+ $this->appendString($source);
+ }
+
+ /**
+ * Appdend a string
+ *
+ * @param string $source
+ * @access public
+ */
+ function appendString($source)
+ {
+ $this->tokenization = array('');
+ for ($i = 0; $i < strlen($source); $i++) {
+ if (strlen($this->ansi)) {
+ $this->ansi.= $source[$i];
+ $chr = ord($source[$i]);
+ // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
+ // single character CSI's not currently supported
+ switch (true) {
+ case $this->ansi == "\x1B=":
+ $this->ansi = '';
+ continue 2;
+ case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
+ case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
+ break;
+ default:
+ continue 2;
+ }
+ $this->tokenization[] = $this->ansi;
+ $this->tokenization[] = '';
+ // http://ascii-table.com/ansi-escape-sequences-vt-100.php
+ switch ($this->ansi) {
+ case "\x1B[H": // Move cursor to upper left corner
+ $this->old_x = $this->x;
+ $this->old_y = $this->y;
+ $this->x = $this->y = 0;
+ break;
+ case "\x1B[J": // Clear screen from cursor down
+ $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
+ $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
+
+ $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
+ $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
+
+ if (count($this->history) == $this->max_history) {
+ array_shift($this->history);
+ array_shift($this->history_attrs);
+ }
+ case "\x1B[K": // Clear screen from cursor right
+ $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
+
+ array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
+ break;
+ case "\x1B[2K": // Clear entire line
+ $this->screen[$this->y] = str_repeat(' ', $this->x);
+ $this->attrs[$this->y] = $this->attr_row;
+ break;
+ case "\x1B[?1h": // set cursor key to application
+ case "\x1B[?25h": // show the cursor
+ case "\x1B(B": // set united states g0 character set
+ break;
+ case "\x1BE": // Move to next line
+ $this->_newLine();
+ $this->x = 0;
+ break;
+ default:
+ switch (true) {
+ case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
+ $this->old_y = $this->y;
+ $this->y+= $match[1];
+ break;
+ case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
+ $this->old_x = $this->x;
+ $this->old_y = $this->y;
+ $this->x = $match[2] - 1;
+ $this->y = $match[1] - 1;
+ break;
+ case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
+ $this->old_x = $this->x;
+ $this->x+= $match[1];
+ break;
+ case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
+ $this->old_x = $this->x;
+ $this->x-= $match[1];
+ if ($this->x < 0) {
+ $this->x = 0;
+ }
+ break;
+ case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
+ break;
+ case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
+ $attr_cell = &$this->attr_cell;
+ $mods = explode(';', $match[1]);
+ foreach ($mods as $mod) {
+ switch ($mod) {
+ case 0: // Turn off character attributes
+ $attr_cell = clone $this->base_attr_cell;
+ break;
+ case 1: // Turn bold mode on
+ $attr_cell->bold = true;
+ break;
+ case 4: // Turn underline mode on
+ $attr_cell->underline = true;
+ break;
+ case 5: // Turn blinking mode on
+ $attr_cell->blink = true;
+ break;
+ case 7: // Turn reverse video on
+ $attr_cell->reverse = !$attr_cell->reverse;
+ $temp = $attr_cell->background;
+ $attr_cell->background = $attr_cell->foreground;
+ $attr_cell->foreground = $temp;
+ break;
+ default: // set colors
+ //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
+ $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
+ //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
+ $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
+ switch ($mod) {
+ // @codingStandardsIgnoreStart
+ case 30: $front = 'black'; break;
+ case 31: $front = 'red'; break;
+ case 32: $front = 'green'; break;
+ case 33: $front = 'yellow'; break;
+ case 34: $front = 'blue'; break;
+ case 35: $front = 'magenta'; break;
+ case 36: $front = 'cyan'; break;
+ case 37: $front = 'white'; break;
+
+ case 40: $back = 'black'; break;
+ case 41: $back = 'red'; break;
+ case 42: $back = 'green'; break;
+ case 43: $back = 'yellow'; break;
+ case 44: $back = 'blue'; break;
+ case 45: $back = 'magenta'; break;
+ case 46: $back = 'cyan'; break;
+ case 47: $back = 'white'; break;
+ // @codingStandardsIgnoreEnd
+
+ default:
+ //user_error('Unsupported attribute: ' . $mod);
+ $this->ansi = '';
+ break 2;
+ }
+ }
+ }
+ break;
+ default:
+ //user_error("{$this->ansi} is unsupported\r\n");
+ }
+ }
+ $this->ansi = '';
+ continue;
+ }
+
+ $this->tokenization[count($this->tokenization) - 1].= $source[$i];
+ switch ($source[$i]) {
+ case "\r":
+ $this->x = 0;
+ break;
+ case "\n":
+ $this->_newLine();
+ break;
+ case "\x08": // backspace
+ if ($this->x) {
+ $this->x--;
+ $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell;
+ $this->screen[$this->y] = substr_replace(
+ $this->screen[$this->y],
+ $source[$i],
+ $this->x,
+ 1
+ );
+ }
+ break;
+ case "\x0F": // shift
+ break;
+ case "\x1B": // start ANSI escape code
+ $this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
+ //if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
+ // array_pop($this->tokenization);
+ //}
+ $this->ansi.= "\x1B";
+ break;
+ default:
+ $this->attrs[$this->y][$this->x] = clone $this->attr_cell;
+ if ($this->x > strlen($this->screen[$this->y])) {
+ $this->screen[$this->y] = str_repeat(' ', $this->x);
+ }
+ $this->screen[$this->y] = substr_replace(
+ $this->screen[$this->y],
+ $source[$i],
+ $this->x,
+ 1
+ );
+
+ if ($this->x > $this->max_x) {
+ $this->x = 0;
+ $this->_newLine();
+ } else {
+ $this->x++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a new line
+ *
+ * Also update the $this->screen and $this->history buffers
+ *
+ * @access private
+ */
+ function _newLine()
+ {
+ //if ($this->y < $this->max_y) {
+ // $this->y++;
+ //}
+
+ while ($this->y >= $this->max_y) {
+ $this->history = array_merge($this->history, array(array_shift($this->screen)));
+ $this->screen[] = '';
+
+ $this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
+ $this->attrs[] = $this->attr_row;
+
+ if (count($this->history) >= $this->max_history) {
+ array_shift($this->history);
+ array_shift($this->history_attrs);
+ }
+
+ $this->y--;
+ }
+ $this->y++;
+ }
+
+ /**
+ * Returns the current coordinate without preformating
+ *
+ * @access private
+ * @return string
+ */
+ function _processCoordinate($last_attr, $cur_attr, $char)
+ {
+ $output = '';
+
+ if ($last_attr != $cur_attr) {
+ $close = $open = '';
+ if ($last_attr->foreground != $cur_attr->foreground) {
+ if ($cur_attr->foreground != 'white') {
+ $open.= '<span style="color: ' . $cur_attr->foreground . '">';
+ }
+ if ($last_attr->foreground != 'white') {
+ $close = '</span>' . $close;
+ }
+ }
+ if ($last_attr->background != $cur_attr->background) {
+ if ($cur_attr->background != 'black') {
+ $open.= '<span style="background: ' . $cur_attr->background . '">';
+ }
+ if ($last_attr->background != 'black') {
+ $close = '</span>' . $close;
+ }
+ }
+ if ($last_attr->bold != $cur_attr->bold) {
+ if ($cur_attr->bold) {
+ $open.= '<b>';
+ } else {
+ $close = '</b>' . $close;
+ }
+ }
+ if ($last_attr->underline != $cur_attr->underline) {
+ if ($cur_attr->underline) {
+ $open.= '<u>';
+ } else {
+ $close = '</u>' . $close;
+ }
+ }
+ if ($last_attr->blink != $cur_attr->blink) {
+ if ($cur_attr->blink) {
+ $open.= '<blink>';
+ } else {
+ $close = '</blink>' . $close;
+ }
+ }
+ $output.= $close . $open;
+ }
+
+ $output.= htmlspecialchars($char);
+
+ return $output;
+ }
+
+ /**
+ * Returns the current screen without preformating
+ *
+ * @access private
+ * @return string
+ */
+ function _getScreen()
+ {
+ $output = '';
+ $last_attr = $this->base_attr_cell;
+ for ($i = 0; $i <= $this->max_y; $i++) {
+ for ($j = 0; $j <= $this->max_x; $j++) {
+ $cur_attr = $this->attrs[$i][$j];
+ $output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
+ $last_attr = $this->attrs[$i][$j];
+ }
+ $output.= "\r\n";
+ }
+ $output = substr($output, 0, -2);
+ // close any remaining open tags
+ $output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
+ return rtrim($output);
+ }
+
+ /**
+ * Returns the current screen
+ *
+ * @access public
+ * @return string
+ */
+ function getScreen()
+ {
+ return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
+ }
+
+ /**
+ * Returns the current screen and the x previous lines
+ *
+ * @access public
+ * @return string
+ */
+ function getHistory()
+ {
+ $scrollback = '';
+ $last_attr = $this->base_attr_cell;
+ for ($i = 0; $i < count($this->history); $i++) {
+ for ($j = 0; $j <= $this->max_x + 1; $j++) {
+ $cur_attr = $this->history_attrs[$i][$j];
+ $scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
+ $last_attr = $this->history_attrs[$i][$j];
+ }
+ $scrollback.= "\r\n";
+ }
+ $base_attr_cell = $this->base_attr_cell;
+ $this->base_attr_cell = $last_attr;
+ $scrollback.= $this->_getScreen();
+ $this->base_attr_cell = $base_attr_cell;
+
+ return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP ASN.1 Parser
+ *
+ * PHP version 5
+ *
+ * ASN.1 provides the semantics for data encoded using various schemes. The most commonly
+ * utilized scheme is DER or the "Distinguished Encoding Rules". PEM's are base64 encoded
+ * DER blobs.
+ *
+ * \phpseclib\File\ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
+ *
+ * Uses the 1988 ASN.1 syntax.
+ *
+ * @category File
+ * @package ASN1
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2012 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\File;
+
+use phpseclib\File\ASN1\Element;
+use phpseclib\Math\BigInteger;
+use DateTime;
+use DateTimeZone;
+
+/**
+ * Pure-PHP ASN.1 Parser
+ *
+ * @package ASN1
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class ASN1
+{
+ /**#@+
+ * Tag Classes
+ *
+ * @access private
+ * @link http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
+ */
+ const CLASS_UNIVERSAL = 0;
+ const CLASS_APPLICATION = 1;
+ const CLASS_CONTEXT_SPECIFIC = 2;
+ const CLASS_PRIVATE = 3;
+ /**#@-*/
+
+ /**#@+
+ * Tag Classes
+ *
+ * @access private
+ * @link http://www.obj-sys.com/asn1tutorial/node124.html
+ */
+ const TYPE_BOOLEAN = 1;
+ const TYPE_INTEGER = 2;
+ const TYPE_BIT_STRING = 3;
+ const TYPE_OCTET_STRING = 4;
+ const TYPE_NULL = 5;
+ const TYPE_OBJECT_IDENTIFIER = 6;
+ //const TYPE_OBJECT_DESCRIPTOR = 7;
+ //const TYPE_INSTANCE_OF = 8; // EXTERNAL
+ const TYPE_REAL = 9;
+ const TYPE_ENUMERATED = 10;
+ //const TYPE_EMBEDDED = 11;
+ const TYPE_UTF8_STRING = 12;
+ //const TYPE_RELATIVE_OID = 13;
+ const TYPE_SEQUENCE = 16; // SEQUENCE OF
+ const TYPE_SET = 17; // SET OF
+ /**#@-*/
+ /**#@+
+ * More Tag Classes
+ *
+ * @access private
+ * @link http://www.obj-sys.com/asn1tutorial/node10.html
+ */
+ const TYPE_NUMERIC_STRING = 18;
+ const TYPE_PRINTABLE_STRING = 19;
+ const TYPE_TELETEX_STRING = 20; // T61String
+ const TYPE_VIDEOTEX_STRING = 21;
+ const TYPE_IA5_STRING = 22;
+ const TYPE_UTC_TIME = 23;
+ const TYPE_GENERALIZED_TIME = 24;
+ const TYPE_GRAPHIC_STRING = 25;
+ const TYPE_VISIBLE_STRING = 26; // ISO646String
+ const TYPE_GENERAL_STRING = 27;
+ const TYPE_UNIVERSAL_STRING = 28;
+ //const TYPE_CHARACTER_STRING = 29;
+ const TYPE_BMP_STRING = 30;
+ /**#@-*/
+
+ /**#@+
+ * Tag Aliases
+ *
+ * These tags are kinda place holders for other tags.
+ *
+ * @access private
+ */
+ const TYPE_CHOICE = -1;
+ const TYPE_ANY = -2;
+ /**#@-*/
+
+ /**
+ * ASN.1 object identifier
+ *
+ * @var array
+ * @access private
+ * @link http://en.wikipedia.org/wiki/Object_identifier
+ */
+ var $oids = array();
+
+ /**
+ * Default date format
+ *
+ * @var string
+ * @access private
+ * @link http://php.net/class.datetime
+ */
+ var $format = 'D, d M Y H:i:s O';
+
+ /**
+ * Default date format
+ *
+ * @var array
+ * @access private
+ * @see self::setTimeFormat()
+ * @see self::asn1map()
+ * @link http://php.net/class.datetime
+ */
+ var $encoded;
+
+ /**
+ * Filters
+ *
+ * If the mapping type is self::TYPE_ANY what do we actually encode it as?
+ *
+ * @var array
+ * @access private
+ * @see self::_encode_der()
+ */
+ var $filters;
+
+ /**
+ * Type mapping table for the ANY type.
+ *
+ * Structured or unknown types are mapped to a \phpseclib\File\ASN1\Element.
+ * Unambiguous types get the direct mapping (int/real/bool).
+ * Others are mapped as a choice, with an extra indexing level.
+ *
+ * @var array
+ * @access public
+ */
+ var $ANYmap = array(
+ self::TYPE_BOOLEAN => true,
+ self::TYPE_INTEGER => true,
+ self::TYPE_BIT_STRING => 'bitString',
+ self::TYPE_OCTET_STRING => 'octetString',
+ self::TYPE_NULL => 'null',
+ self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
+ self::TYPE_REAL => true,
+ self::TYPE_ENUMERATED => 'enumerated',
+ self::TYPE_UTF8_STRING => 'utf8String',
+ self::TYPE_NUMERIC_STRING => 'numericString',
+ self::TYPE_PRINTABLE_STRING => 'printableString',
+ self::TYPE_TELETEX_STRING => 'teletexString',
+ self::TYPE_VIDEOTEX_STRING => 'videotexString',
+ self::TYPE_IA5_STRING => 'ia5String',
+ self::TYPE_UTC_TIME => 'utcTime',
+ self::TYPE_GENERALIZED_TIME => 'generalTime',
+ self::TYPE_GRAPHIC_STRING => 'graphicString',
+ self::TYPE_VISIBLE_STRING => 'visibleString',
+ self::TYPE_GENERAL_STRING => 'generalString',
+ self::TYPE_UNIVERSAL_STRING => 'universalString',
+ //self::TYPE_CHARACTER_STRING => 'characterString',
+ self::TYPE_BMP_STRING => 'bmpString'
+ );
+
+ /**
+ * String type to character size mapping table.
+ *
+ * Non-convertable types are absent from this table.
+ * size == 0 indicates variable length encoding.
+ *
+ * @var array
+ * @access public
+ */
+ var $stringTypeSize = array(
+ self::TYPE_UTF8_STRING => 0,
+ self::TYPE_BMP_STRING => 2,
+ self::TYPE_UNIVERSAL_STRING => 4,
+ self::TYPE_PRINTABLE_STRING => 1,
+ self::TYPE_TELETEX_STRING => 1,
+ self::TYPE_IA5_STRING => 1,
+ self::TYPE_VISIBLE_STRING => 1,
+ );
+
+ /**
+ * Parse BER-encoding
+ *
+ * Serves a similar purpose to openssl's asn1parse
+ *
+ * @param string $encoded
+ * @return array
+ * @access public
+ */
+ function decodeBER($encoded)
+ {
+ if ($encoded instanceof Element) {
+ $encoded = $encoded->element;
+ }
+
+ $this->encoded = $encoded;
+ // encapsulate in an array for BC with the old decodeBER
+ return array($this->_decode_ber($encoded));
+ }
+
+ /**
+ * Parse BER-encoding (Helper function)
+ *
+ * Sometimes we want to get the BER encoding of a particular tag. $start lets us do that without having to reencode.
+ * $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and
+ * self::TYPE_OCTET_STRING. In those cases, the indefinite length is used.
+ *
+ * @param string $encoded
+ * @param int $start
+ * @param int $encoded_pos
+ * @return array
+ * @access private
+ */
+ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
+ {
+ $current = array('start' => $start);
+
+ $type = ord($encoded[$encoded_pos++]);
+ $start++;
+
+ $constructed = ($type >> 5) & 1;
+
+ $tag = $type & 0x1F;
+ if ($tag == 0x1F) {
+ $tag = 0;
+ // process septets (since the eighth bit is ignored, it's not an octet)
+ do {
+ $temp = ord($encoded[$encoded_pos++]);
+ $loop = $temp >> 7;
+ $tag <<= 7;
+ $tag |= $temp & 0x7F;
+ $start++;
+ } while ($loop);
+ }
+
+ // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
+ $length = ord($encoded[$encoded_pos++]);
+ $start++;
+ if ($length == 0x80) { // indefinite length
+ // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
+ // immediately available." -- paragraph 8.1.3.2.c
+ $length = strlen($encoded) - $encoded_pos;
+ } elseif ($length & 0x80) { // definite length, long form
+ // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
+ // support it up to four.
+ $length&= 0x7F;
+ $temp = substr($encoded, $encoded_pos, $length);
+ $encoded_pos += $length;
+ // tags of indefinte length don't really have a header length; this length includes the tag
+ $current+= array('headerlength' => $length + 2);
+ $start+= $length;
+ extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
+ } else {
+ $current+= array('headerlength' => 2);
+ }
+
+ if ($length > (strlen($encoded) - $encoded_pos)) {
+ return false;
+ }
+
+ $content = substr($encoded, $encoded_pos, $length);
+ $content_pos = 0;
+
+ // at this point $length can be overwritten. it's only accurate for definite length things as is
+
+ /* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
+ built-in types. It defines an application-independent data type that must be distinguishable from all other
+ data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
+ have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
+ a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
+ alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
+ data type; the term CONTEXT-SPECIFIC does not appear.
+
+ -- http://www.obj-sys.com/asn1tutorial/node12.html */
+ $class = ($type >> 6) & 3;
+ switch ($class) {
+ case self::CLASS_APPLICATION:
+ case self::CLASS_PRIVATE:
+ case self::CLASS_CONTEXT_SPECIFIC:
+ if (!$constructed) {
+ return array(
+ 'type' => $class,
+ 'constant' => $tag,
+ 'content' => $content,
+ 'length' => $length + $start - $current['start']
+ );
+ }
+
+ $newcontent = array();
+ $remainingLength = $length;
+ while ($remainingLength > 0) {
+ $temp = $this->_decode_ber($content, $start, $content_pos);
+ if ($temp === false) {
+ break;
+ }
+ $length = $temp['length'];
+ // end-of-content octets - see paragraph 8.1.5
+ if (substr($content, $content_pos + $length, 2) == "\0\0") {
+ $length+= 2;
+ $start+= $length;
+ $newcontent[] = $temp;
+ break;
+ }
+ $start+= $length;
+ $remainingLength-= $length;
+ $newcontent[] = $temp;
+ $content_pos += $length;
+ }
+
+ return array(
+ 'type' => $class,
+ 'constant' => $tag,
+ // the array encapsulation is for BC with the old format
+ 'content' => $newcontent,
+ // the only time when $content['headerlength'] isn't defined is when the length is indefinite.
+ // the absence of $content['headerlength'] is how we know if something is indefinite or not.
+ // technically, it could be defined to be 2 and then another indicator could be used but whatever.
+ 'length' => $start - $current['start']
+ ) + $current;
+ }
+
+ $current+= array('type' => $tag);
+
+ // decode UNIVERSAL tags
+ switch ($tag) {
+ case self::TYPE_BOOLEAN:
+ // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
+ //if (strlen($content) != 1) {
+ // return false;
+ //}
+ $current['content'] = (bool) ord($content[$content_pos]);
+ break;
+ case self::TYPE_INTEGER:
+ case self::TYPE_ENUMERATED:
+ $current['content'] = new BigInteger(substr($content, $content_pos), -256);
+ break;
+ case self::TYPE_REAL: // not currently supported
+ return false;
+ case self::TYPE_BIT_STRING:
+ // The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
+ // the number of unused bits in the final subsequent octet. The number shall be in the range zero to
+ // seven.
+ if (!$constructed) {
+ $current['content'] = substr($content, $content_pos);
+ } else {
+ $temp = $this->_decode_ber($content, $start, $content_pos);
+ if ($temp === false) {
+ return false;
+ }
+ $length-= (strlen($content) - $content_pos);
+ $last = count($temp) - 1;
+ for ($i = 0; $i < $last; $i++) {
+ // all subtags should be bit strings
+ //if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
+ // return false;
+ //}
+ $current['content'].= substr($temp[$i]['content'], 1);
+ }
+ // all subtags should be bit strings
+ //if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
+ // return false;
+ //}
+ $current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
+ }
+ break;
+ case self::TYPE_OCTET_STRING:
+ if (!$constructed) {
+ $current['content'] = substr($content, $content_pos);
+ } else {
+ $current['content'] = '';
+ $length = 0;
+ while (substr($content, $content_pos, 2) != "\0\0") {
+ $temp = $this->_decode_ber($content, $length + $start, $content_pos);
+ if ($temp === false) {
+ return false;
+ }
+ $content_pos += $temp['length'];
+ // all subtags should be octet strings
+ //if ($temp['type'] != self::TYPE_OCTET_STRING) {
+ // return false;
+ //}
+ $current['content'].= $temp['content'];
+ $length+= $temp['length'];
+ }
+ if (substr($content, $content_pos, 2) == "\0\0") {
+ $length+= 2; // +2 for the EOC
+ }
+ }
+ break;
+ case self::TYPE_NULL:
+ // "The contents octets shall not contain any octets." -- paragraph 8.8.2
+ //if (strlen($content)) {
+ // return false;
+ //}
+ break;
+ case self::TYPE_SEQUENCE:
+ case self::TYPE_SET:
+ $offset = 0;
+ $current['content'] = array();
+ $content_len = strlen($content);
+ while ($content_pos < $content_len) {
+ // if indefinite length construction was used and we have an end-of-content string next
+ // see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
+ if (!isset($current['headerlength']) && substr($content, $content_pos, 2) == "\0\0") {
+ $length = $offset + 2; // +2 for the EOC
+ break 2;
+ }
+ $temp = $this->_decode_ber($content, $start + $offset, $content_pos);
+ if ($temp === false) {
+ return false;
+ }
+ $content_pos += $temp['length'];
+ $current['content'][] = $temp;
+ $offset+= $temp['length'];
+ }
+ break;
+ case self::TYPE_OBJECT_IDENTIFIER:
+ $current['content'] = $this->_decodeOID(substr($content, $content_pos));
+ break;
+ /* Each character string type shall be encoded as if it had been declared:
+ [UNIVERSAL x] IMPLICIT OCTET STRING
+
+ -- X.690-0207.pdf#page=23 (paragraph 8.21.3)
+
+ Per that, we're not going to do any validation. If there are any illegal characters in the string,
+ we don't really care */
+ case self::TYPE_NUMERIC_STRING:
+ // 0,1,2,3,4,5,6,7,8,9, and space
+ case self::TYPE_PRINTABLE_STRING:
+ // Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
+ // hyphen, full stop, solidus, colon, equal sign, question mark
+ case self::TYPE_TELETEX_STRING:
+ // The Teletex character set in CCITT's T61, space, and delete
+ // see http://en.wikipedia.org/wiki/Teletex#Character_sets
+ case self::TYPE_VIDEOTEX_STRING:
+ // The Videotex character set in CCITT's T.100 and T.101, space, and delete
+ case self::TYPE_VISIBLE_STRING:
+ // Printing character sets of international ASCII, and space
+ case self::TYPE_IA5_STRING:
+ // International Alphabet 5 (International ASCII)
+ case self::TYPE_GRAPHIC_STRING:
+ // All registered G sets, and space
+ case self::TYPE_GENERAL_STRING:
+ // All registered C and G sets, space and delete
+ case self::TYPE_UTF8_STRING:
+ // ????
+ case self::TYPE_BMP_STRING:
+ $current['content'] = substr($content, $content_pos);
+ break;
+ case self::TYPE_UTC_TIME:
+ case self::TYPE_GENERALIZED_TIME:
+ $current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
+ default:
+ }
+
+ $start+= $length;
+
+ // ie. length is the length of the full TLV encoding - it's not just the length of the value
+ return $current + array('length' => $start - $current['start']);
+ }
+
+ /**
+ * ASN.1 Map
+ *
+ * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
+ *
+ * "Special" mappings may be applied on a per tag-name basis via $special.
+ *
+ * @param array $decoded
+ * @param array $mapping
+ * @param array $special
+ * @return array
+ * @access public
+ */
+ function asn1map($decoded, $mapping, $special = array())
+ {
+ if (isset($mapping['explicit']) && is_array($decoded['content'])) {
+ $decoded = $decoded['content'][0];
+ }
+
+ switch (true) {
+ case $mapping['type'] == self::TYPE_ANY:
+ $intype = $decoded['type'];
+ if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || (ord($this->encoded[$decoded['start']]) & 0x20)) {
+ return new Element(substr($this->encoded, $decoded['start'], $decoded['length']));
+ }
+ $inmap = $this->ANYmap[$intype];
+ if (is_string($inmap)) {
+ return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping, $special));
+ }
+ break;
+ case $mapping['type'] == self::TYPE_CHOICE:
+ foreach ($mapping['children'] as $key => $option) {
+ switch (true) {
+ case isset($option['constant']) && $option['constant'] == $decoded['constant']:
+ case !isset($option['constant']) && $option['type'] == $decoded['type']:
+ $value = $this->asn1map($decoded, $option, $special);
+ break;
+ case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE:
+ $v = $this->asn1map($decoded, $option, $special);
+ if (isset($v)) {
+ $value = $v;
+ }
+ }
+ if (isset($value)) {
+ if (isset($special[$key])) {
+ $value = call_user_func($special[$key], $value);
+ }
+ return array($key => $value);
+ }
+ }
+ return null;
+ case isset($mapping['implicit']):
+ case isset($mapping['explicit']):
+ case $decoded['type'] == $mapping['type']:
+ break;
+ default:
+ // if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
+ // let it through
+ switch (true) {
+ case $decoded['type'] < 18: // self::TYPE_NUMERIC_STRING == 18
+ case $decoded['type'] > 30: // self::TYPE_BMP_STRING == 30
+ case $mapping['type'] < 18:
+ case $mapping['type'] > 30:
+ return null;
+ }
+ }
+
+ if (isset($mapping['implicit'])) {
+ $decoded['type'] = $mapping['type'];
+ }
+
+ switch ($decoded['type']) {
+ case self::TYPE_SEQUENCE:
+ $map = array();
+
+ // ignore the min and max
+ if (isset($mapping['min']) && isset($mapping['max'])) {
+ $child = $mapping['children'];
+ foreach ($decoded['content'] as $content) {
+ if (($map[] = $this->asn1map($content, $child, $special)) === null) {
+ return null;
+ }
+ }
+
+ return $map;
+ }
+
+ $n = count($decoded['content']);
+ $i = 0;
+
+ foreach ($mapping['children'] as $key => $child) {
+ $maymatch = $i < $n; // Match only existing input.
+ if ($maymatch) {
+ $temp = $decoded['content'][$i];
+
+ if ($child['type'] != self::TYPE_CHOICE) {
+ // Get the mapping and input class & constant.
+ $childClass = $tempClass = self::CLASS_UNIVERSAL;
+ $constant = null;
+ if (isset($temp['constant'])) {
+ $tempClass = $temp['type'];
+ }
+ if (isset($child['class'])) {
+ $childClass = $child['class'];
+ $constant = $child['cast'];
+ } elseif (isset($child['constant'])) {
+ $childClass = self::CLASS_CONTEXT_SPECIFIC;
+ $constant = $child['constant'];
+ }
+
+ if (isset($constant) && isset($temp['constant'])) {
+ // Can only match if constants and class match.
+ $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
+ } else {
+ // Can only match if no constant expected and type matches or is generic.
+ $maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== false;
+ }
+ }
+ }
+
+ if ($maymatch) {
+ // Attempt submapping.
+ $candidate = $this->asn1map($temp, $child, $special);
+ $maymatch = $candidate !== null;
+ }
+
+ if ($maymatch) {
+ // Got the match: use it.
+ if (isset($special[$key])) {
+ $candidate = call_user_func($special[$key], $candidate);
+ }
+ $map[$key] = $candidate;
+ $i++;
+ } elseif (isset($child['default'])) {
+ $map[$key] = $child['default']; // Use default.
+ } elseif (!isset($child['optional'])) {
+ return null; // Syntax error.
+ }
+ }
+
+ // Fail mapping if all input items have not been consumed.
+ return $i < $n ? null: $map;
+
+ // the main diff between sets and sequences is the encapsulation of the foreach in another for loop
+ case self::TYPE_SET:
+ $map = array();
+
+ // ignore the min and max
+ if (isset($mapping['min']) && isset($mapping['max'])) {
+ $child = $mapping['children'];
+ foreach ($decoded['content'] as $content) {
+ if (($map[] = $this->asn1map($content, $child, $special)) === null) {
+ return null;
+ }
+ }
+
+ return $map;
+ }
+
+ for ($i = 0; $i < count($decoded['content']); $i++) {
+ $temp = $decoded['content'][$i];
+ $tempClass = self::CLASS_UNIVERSAL;
+ if (isset($temp['constant'])) {
+ $tempClass = $temp['type'];
+ }
+
+ foreach ($mapping['children'] as $key => $child) {
+ if (isset($map[$key])) {
+ continue;
+ }
+ $maymatch = true;
+ if ($child['type'] != self::TYPE_CHOICE) {
+ $childClass = self::CLASS_UNIVERSAL;
+ $constant = null;
+ if (isset($child['class'])) {
+ $childClass = $child['class'];
+ $constant = $child['cast'];
+ } elseif (isset($child['constant'])) {
+ $childClass = self::CLASS_CONTEXT_SPECIFIC;
+ $constant = $child['constant'];
+ }
+
+ if (isset($constant) && isset($temp['constant'])) {
+ // Can only match if constants and class match.
+ $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
+ } else {
+ // Can only match if no constant expected and type matches or is generic.
+ $maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== false;
+ }
+ }
+
+ if ($maymatch) {
+ // Attempt submapping.
+ $candidate = $this->asn1map($temp, $child, $special);
+ $maymatch = $candidate !== null;
+ }
+
+ if (!$maymatch) {
+ break;
+ }
+
+ // Got the match: use it.
+ if (isset($special[$key])) {
+ $candidate = call_user_func($special[$key], $candidate);
+ }
+ $map[$key] = $candidate;
+ break;
+ }
+ }
+
+ foreach ($mapping['children'] as $key => $child) {
+ if (!isset($map[$key])) {
+ if (isset($child['default'])) {
+ $map[$key] = $child['default'];
+ } elseif (!isset($child['optional'])) {
+ return null;
+ }
+ }
+ }
+ return $map;
+ case self::TYPE_OBJECT_IDENTIFIER:
+ return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content'];
+ case self::TYPE_UTC_TIME:
+ case self::TYPE_GENERALIZED_TIME:
+ if (isset($mapping['implicit'])) {
+ $decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
+ }
+ return $decoded['content'] ? $decoded['content']->format($this->format) : false;
+ case self::TYPE_BIT_STRING:
+ if (isset($mapping['mapping'])) {
+ $offset = ord($decoded['content'][0]);
+ $size = (strlen($decoded['content']) - 1) * 8 - $offset;
+ /*
+ From X.680-0207.pdf#page=46 (21.7):
+
+ "When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove)
+ arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should
+ therefore ensure that different semantics are not associated with such values which differ only in the number of trailing
+ 0 bits."
+ */
+ $bits = count($mapping['mapping']) == $size ? array() : array_fill(0, count($mapping['mapping']) - $size, false);
+ for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) {
+ $current = ord($decoded['content'][$i]);
+ for ($j = $offset; $j < 8; $j++) {
+ $bits[] = (bool) ($current & (1 << $j));
+ }
+ $offset = 0;
+ }
+ $values = array();
+ $map = array_reverse($mapping['mapping']);
+ foreach ($map as $i => $value) {
+ if ($bits[$i]) {
+ $values[] = $value;
+ }
+ }
+ return $values;
+ }
+ case self::TYPE_OCTET_STRING:
+ return base64_encode($decoded['content']);
+ case self::TYPE_NULL:
+ return '';
+ case self::TYPE_BOOLEAN:
+ return $decoded['content'];
+ case self::TYPE_NUMERIC_STRING:
+ case self::TYPE_PRINTABLE_STRING:
+ case self::TYPE_TELETEX_STRING:
+ case self::TYPE_VIDEOTEX_STRING:
+ case self::TYPE_IA5_STRING:
+ case self::TYPE_GRAPHIC_STRING:
+ case self::TYPE_VISIBLE_STRING:
+ case self::TYPE_GENERAL_STRING:
+ case self::TYPE_UNIVERSAL_STRING:
+ case self::TYPE_UTF8_STRING:
+ case self::TYPE_BMP_STRING:
+ return $decoded['content'];
+ case self::TYPE_INTEGER:
+ case self::TYPE_ENUMERATED:
+ $temp = $decoded['content'];
+ if (isset($mapping['implicit'])) {
+ $temp = new BigInteger($decoded['content'], -256);
+ }
+ if (isset($mapping['mapping'])) {
+ $temp = (int) $temp->toString();
+ return isset($mapping['mapping'][$temp]) ?
+ $mapping['mapping'][$temp] :
+ false;
+ }
+ return $temp;
+ }
+ }
+
+ /**
+ * ASN.1 Encode
+ *
+ * DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function
+ * an ASN.1 compiler.
+ *
+ * "Special" mappings can be applied via $special.
+ *
+ * @param string $source
+ * @param string $mapping
+ * @param int $idx
+ * @return string
+ * @access public
+ */
+ function encodeDER($source, $mapping, $special = array())
+ {
+ $this->location = array();
+ return $this->_encode_der($source, $mapping, null, $special);
+ }
+
+ /**
+ * ASN.1 Encode (Helper function)
+ *
+ * @param string $source
+ * @param string $mapping
+ * @param int $idx
+ * @return string
+ * @access private
+ */
+ function _encode_der($source, $mapping, $idx = null, $special = array())
+ {
+ if ($source instanceof Element) {
+ return $source->element;
+ }
+
+ // do not encode (implicitly optional) fields with value set to default
+ if (isset($mapping['default']) && $source === $mapping['default']) {
+ return '';
+ }
+
+ if (isset($idx)) {
+ if (isset($special[$idx])) {
+ $source = call_user_func($special[$idx], $source);
+ }
+ $this->location[] = $idx;
+ }
+
+ $tag = $mapping['type'];
+
+ switch ($tag) {
+ case self::TYPE_SET: // Children order is not important, thus process in sequence.
+ case self::TYPE_SEQUENCE:
+ $tag|= 0x20; // set the constructed bit
+
+ // ignore the min and max
+ if (isset($mapping['min']) && isset($mapping['max'])) {
+ $value = array();
+ $child = $mapping['children'];
+
+ foreach ($source as $content) {
+ $temp = $this->_encode_der($content, $child, null, $special);
+ if ($temp === false) {
+ return false;
+ }
+ $value[]= $temp;
+ }
+ /* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared
+ as octet strings with the shorter components being padded at their trailing end with 0-octets.
+ NOTE - The padding octets are for comparison purposes only and do not appear in the encodings."
+
+ -- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */
+ if ($mapping['type'] == self::TYPE_SET) {
+ sort($value);
+ }
+ $value = implode($value, '');
+ break;
+ }
+
+ $value = '';
+ foreach ($mapping['children'] as $key => $child) {
+ if (!array_key_exists($key, $source)) {
+ if (!isset($child['optional'])) {
+ return false;
+ }
+ continue;
+ }
+
+ $temp = $this->_encode_der($source[$key], $child, $key, $special);
+ if ($temp === false) {
+ return false;
+ }
+
+ // An empty child encoding means it has been optimized out.
+ // Else we should have at least one tag byte.
+ if ($temp === '') {
+ continue;
+ }
+
+ // if isset($child['constant']) is true then isset($child['optional']) should be true as well
+ if (isset($child['constant'])) {
+ /*
+ From X.680-0207.pdf#page=58 (30.6):
+
+ "The tagging construction specifies explicit tagging if any of the following holds:
+ ...
+ c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or
+ AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
+ an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
+ */
+ if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
+ $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
+ $temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
+ } else {
+ $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
+ $temp = $subtag . substr($temp, 1);
+ }
+ }
+ $value.= $temp;
+ }
+ break;
+ case self::TYPE_CHOICE:
+ $temp = false;
+
+ foreach ($mapping['children'] as $key => $child) {
+ if (!isset($source[$key])) {
+ continue;
+ }
+
+ $temp = $this->_encode_der($source[$key], $child, $key, $special);
+ if ($temp === false) {
+ return false;
+ }
+
+ // An empty child encoding means it has been optimized out.
+ // Else we should have at least one tag byte.
+ if ($temp === '') {
+ continue;
+ }
+
+ $tag = ord($temp[0]);
+
+ // if isset($child['constant']) is true then isset($child['optional']) should be true as well
+ if (isset($child['constant'])) {
+ if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
+ $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
+ $temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
+ } else {
+ $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
+ $temp = $subtag . substr($temp, 1);
+ }
+ }
+ }
+
+ if (isset($idx)) {
+ array_pop($this->location);
+ }
+
+ if ($temp && isset($mapping['cast'])) {
+ $temp[0] = chr(($mapping['class'] << 6) | ($tag & 0x20) | $mapping['cast']);
+ }
+
+ return $temp;
+ case self::TYPE_INTEGER:
+ case self::TYPE_ENUMERATED:
+ if (!isset($mapping['mapping'])) {
+ if (is_numeric($source)) {
+ $source = new BigInteger($source);
+ }
+ $value = $source->toBytes(true);
+ } else {
+ $value = array_search($source, $mapping['mapping']);
+ if ($value === false) {
+ return false;
+ }
+ $value = new BigInteger($value);
+ $value = $value->toBytes(true);
+ }
+ if (!strlen($value)) {
+ $value = chr(0);
+ }
+ break;
+ case self::TYPE_UTC_TIME:
+ case self::TYPE_GENERALIZED_TIME:
+ $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
+ $format.= 'mdHis';
+ $date = new DateTime($source, new DateTimeZone('GMT'));
+ $value = $date->format($format) . 'Z';
+ break;
+ case self::TYPE_BIT_STRING:
+ if (isset($mapping['mapping'])) {
+ $bits = array_fill(0, count($mapping['mapping']), 0);
+ $size = 0;
+ for ($i = 0; $i < count($mapping['mapping']); $i++) {
+ if (in_array($mapping['mapping'][$i], $source)) {
+ $bits[$i] = 1;
+ $size = $i;
+ }
+ }
+
+ if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
+ $size = $mapping['min'] - 1;
+ }
+
+ $offset = 8 - (($size + 1) & 7);
+ $offset = $offset !== 8 ? $offset : 0;
+
+ $value = chr($offset);
+
+ for ($i = $size + 1; $i < count($mapping['mapping']); $i++) {
+ unset($bits[$i]);
+ }
+
+ $bits = implode('', array_pad($bits, $size + $offset + 1, 0));
+ $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' ')));
+ foreach ($bytes as $byte) {
+ $value.= chr(bindec($byte));
+ }
+
+ break;
+ }
+ case self::TYPE_OCTET_STRING:
+ /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
+ the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
+
+ -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
+ $value = base64_decode($source);
+ break;
+ case self::TYPE_OBJECT_IDENTIFIER:
+ $value = $this->_encodeOID($source);
+ break;
+ case self::TYPE_ANY:
+ $loc = $this->location;
+ if (isset($idx)) {
+ array_pop($this->location);
+ }
+
+ switch (true) {
+ case !isset($source):
+ return $this->_encode_der(null, array('type' => self::TYPE_NULL) + $mapping, null, $special);
+ case is_int($source):
+ case $source instanceof BigInteger:
+ return $this->_encode_der($source, array('type' => self::TYPE_INTEGER) + $mapping, null, $special);
+ case is_float($source):
+ return $this->_encode_der($source, array('type' => self::TYPE_REAL) + $mapping, null, $special);
+ case is_bool($source):
+ return $this->_encode_der($source, array('type' => self::TYPE_BOOLEAN) + $mapping, null, $special);
+ case is_array($source) && count($source) == 1:
+ $typename = implode('', array_keys($source));
+ $outtype = array_search($typename, $this->ANYmap, true);
+ if ($outtype !== false) {
+ return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special);
+ }
+ }
+
+ $filters = $this->filters;
+ foreach ($loc as $part) {
+ if (!isset($filters[$part])) {
+ $filters = false;
+ break;
+ }
+ $filters = $filters[$part];
+ }
+ if ($filters === false) {
+ user_error('No filters defined for ' . implode('/', $loc));
+ return false;
+ }
+ return $this->_encode_der($source, $filters + $mapping, null, $special);
+ case self::TYPE_NULL:
+ $value = '';
+ break;
+ case self::TYPE_NUMERIC_STRING:
+ case self::TYPE_TELETEX_STRING:
+ case self::TYPE_PRINTABLE_STRING:
+ case self::TYPE_UNIVERSAL_STRING:
+ case self::TYPE_UTF8_STRING:
+ case self::TYPE_BMP_STRING:
+ case self::TYPE_IA5_STRING:
+ case self::TYPE_VISIBLE_STRING:
+ case self::TYPE_VIDEOTEX_STRING:
+ case self::TYPE_GRAPHIC_STRING:
+ case self::TYPE_GENERAL_STRING:
+ $value = $source;
+ break;
+ case self::TYPE_BOOLEAN:
+ $value = $source ? "\xFF" : "\x00";
+ break;
+ default:
+ user_error('Mapping provides no type definition for ' . implode('/', $this->location));
+ return false;
+ }
+
+ if (isset($idx)) {
+ array_pop($this->location);
+ }
+
+ if (isset($mapping['cast'])) {
+ if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) {
+ $value = chr($tag) . $this->_encodeLength(strlen($value)) . $value;
+ $tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast'];
+ } else {
+ $tag = ($mapping['class'] << 6) | (ord($temp[0]) & 0x20) | $mapping['cast'];
+ }
+ }
+
+ return chr($tag) . $this->_encodeLength(strlen($value)) . $value;
+ }
+
+ /**
+ * DER-encode the length
+ *
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
+ *
+ * @access private
+ * @param int $length
+ * @return string
+ */
+ function _encodeLength($length)
+ {
+ if ($length <= 0x7F) {
+ return chr($length);
+ }
+
+ $temp = ltrim(pack('N', $length), chr(0));
+ return pack('Ca*', 0x80 | strlen($temp), $temp);
+ }
+
+ /**
+ * BER-decode the OID
+ *
+ * Called by _decode_ber()
+ *
+ * @access private
+ * @param string $content
+ * @return string
+ */
+ function _decodeOID($content)
+ {
+ static $eighty;
+ if (!$eighty) {
+ $eighty = new BigInteger(80);
+ }
+
+ $oid = array();
+ $pos = 0;
+ $len = strlen($content);
+ $n = new BigInteger();
+ while ($pos < $len) {
+ $temp = ord($content[$pos++]);
+ $n = $n->bitwise_leftShift(7);
+ $n = $n->bitwise_or(new BigInteger($temp & 0x7F));
+ if (~$temp & 0x80) {
+ $oid[] = $n;
+ $n = new BigInteger();
+ }
+ }
+ $part1 = array_shift($oid);
+ $first = floor(ord($content[0]) / 40);
+ /*
+ "This packing of the first two object identifier components recognizes that only three values are allocated from the root
+ node, and at most 39 subsequent values from nodes reached by X = 0 and X = 1."
+
+ -- https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22
+ */
+ if ($first <= 2) { // ie. 0 <= ord($content[0]) < 120 (0x78)
+ array_unshift($oid, ord($content[0]) % 40);
+ array_unshift($oid, $first);
+ } else {
+ array_unshift($oid, $part1->subtract($eighty));
+ array_unshift($oid, 2);
+ }
+
+ return implode('.', $oid);
+ }
+
+ /**
+ * DER-encode the OID
+ *
+ * Called by _encode_der()
+ *
+ * @access private
+ * @param string $content
+ * @return string
+ */
+ function _encodeOID($source)
+ {
+ static $mask, $zero, $forty;
+ if (!$mask) {
+ $mask = new BigInteger(0x7F);
+ $zero = new BigInteger();
+ $forty = new BigInteger(40);
+ }
+
+ $oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
+ if ($oid === false) {
+ user_error('Invalid OID');
+ return false;
+ }
+ $parts = explode('.', $oid);
+ $part1 = array_shift($parts);
+ $part2 = array_shift($parts);
+
+ $first = new BigInteger($part1);
+ $first = $first->multiply($forty);
+ $first = $first->add(new BigInteger($part2));
+
+ array_unshift($parts, $first->toString());
+
+ $value = '';
+ foreach ($parts as $part) {
+ if (!$part) {
+ $temp = "\0";
+ } else {
+ $temp = '';
+ $part = new BigInteger($part);
+ while (!$part->equals($zero)) {
+ $submask = $part->bitwise_and($mask);
+ $submask->setPrecision(8);
+ $temp = (chr(0x80) | $submask->toBytes()) . $temp;
+ $part = $part->bitwise_rightShift(7);
+ }
+ $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
+ }
+ $value.= $temp;
+ }
+
+ return $value;
+ }
+
+ /**
+ * BER-decode the time
+ *
+ * Called by _decode_ber() and in the case of implicit tags asn1map().
+ *
+ * @access private
+ * @param string $content
+ * @param int $tag
+ * @return string
+ */
+ function _decodeTime($content, $tag)
+ {
+ /* UTCTime:
+ http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
+ http://www.obj-sys.com/asn1tutorial/node15.html
+
+ GeneralizedTime:
+ http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
+ http://www.obj-sys.com/asn1tutorial/node14.html */
+
+ $format = 'YmdHis';
+
+ if ($tag == self::TYPE_UTC_TIME) {
+ // https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
+ // element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
+ // browsers parse it phpseclib ought to too
+ if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) {
+ $content = $matches[1] . '00' . $matches[2];
+ }
+ $prefix = substr($content, 0, 2) >= 50 ? '19' : '20';
+ $content = $prefix . $content;
+ } elseif (strpos($content, '.') !== false) {
+ $format.= '.u';
+ }
+
+ if ($content[strlen($content) - 1] == 'Z') {
+ $content = substr($content, 0, -1) . '+0000';
+ }
+
+ if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
+ $format.= 'O';
+ }
+
+ // error supression isn't necessary as of PHP 7.0:
+ // http://php.net/manual/en/migration70.other-changes.php
+ return @DateTime::createFromFormat($format, $content);
+ }
+
+ /**
+ * Set the time format
+ *
+ * Sets the time / date format for asn1map().
+ *
+ * @access public
+ * @param string $format
+ */
+ function setTimeFormat($format)
+ {
+ $this->format = $format;
+ }
+
+ /**
+ * Load OIDs
+ *
+ * Load the relevant OIDs for a particular ASN.1 semantic mapping.
+ *
+ * @access public
+ * @param array $oids
+ */
+ function loadOIDs($oids)
+ {
+ $this->oids = $oids;
+ }
+
+ /**
+ * Load filters
+ *
+ * See \phpseclib\File\X509, etc, for an example.
+ *
+ * @access public
+ * @param array $filters
+ */
+ function loadFilters($filters)
+ {
+ $this->filters = $filters;
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @return string
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+
+ /**
+ * String type conversion
+ *
+ * This is a lazy conversion, dealing only with character size.
+ * No real conversion table is used.
+ *
+ * @param string $in
+ * @param int $from
+ * @param int $to
+ * @return string
+ * @access public
+ */
+ function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)
+ {
+ if (!isset($this->stringTypeSize[$from]) || !isset($this->stringTypeSize[$to])) {
+ return false;
+ }
+ $insize = $this->stringTypeSize[$from];
+ $outsize = $this->stringTypeSize[$to];
+ $inlength = strlen($in);
+ $out = '';
+
+ for ($i = 0; $i < $inlength;) {
+ if ($inlength - $i < $insize) {
+ return false;
+ }
+
+ // Get an input character as a 32-bit value.
+ $c = ord($in[$i++]);
+ switch (true) {
+ case $insize == 4:
+ $c = ($c << 8) | ord($in[$i++]);
+ $c = ($c << 8) | ord($in[$i++]);
+ case $insize == 2:
+ $c = ($c << 8) | ord($in[$i++]);
+ case $insize == 1:
+ break;
+ case ($c & 0x80) == 0x00:
+ break;
+ case ($c & 0x40) == 0x00:
+ return false;
+ default:
+ $bit = 6;
+ do {
+ if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xC0) != 0x80) {
+ return false;
+ }
+ $c = ($c << 6) | (ord($in[$i++]) & 0x3F);
+ $bit += 5;
+ $mask = 1 << $bit;
+ } while ($c & $bit);
+ $c &= $mask - 1;
+ break;
+ }
+
+ // Convert and append the character to output string.
+ $v = '';
+ switch (true) {
+ case $outsize == 4:
+ $v .= chr($c & 0xFF);
+ $c >>= 8;
+ $v .= chr($c & 0xFF);
+ $c >>= 8;
+ case $outsize == 2:
+ $v .= chr($c & 0xFF);
+ $c >>= 8;
+ case $outsize == 1:
+ $v .= chr($c & 0xFF);
+ $c >>= 8;
+ if ($c) {
+ return false;
+ }
+ break;
+ case ($c & 0x80000000) != 0:
+ return false;
+ case $c >= 0x04000000:
+ $v .= chr(0x80 | ($c & 0x3F));
+ $c = ($c >> 6) | 0x04000000;
+ case $c >= 0x00200000:
+ $v .= chr(0x80 | ($c & 0x3F));
+ $c = ($c >> 6) | 0x00200000;
+ case $c >= 0x00010000:
+ $v .= chr(0x80 | ($c & 0x3F));
+ $c = ($c >> 6) | 0x00010000;
+ case $c >= 0x00000800:
+ $v .= chr(0x80 | ($c & 0x3F));
+ $c = ($c >> 6) | 0x00000800;
+ case $c >= 0x00000080:
+ $v .= chr(0x80 | ($c & 0x3F));
+ $c = ($c >> 6) | 0x000000C0;
+ default:
+ $v .= chr($c);
+ break;
+ }
+ $out .= strrev($v);
+ }
+ return $out;
+ }
+}
--- /dev/null
+<?php
+/**
+ * Pure-PHP ASN.1 Parser
+ *
+ * PHP version 5
+ *
+ * @category File
+ * @package ASN1
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2012 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\File\ASN1;
+
+/**
+ * ASN.1 Element
+ *
+ * Bypass normal encoding rules in phpseclib\File\ASN1::encodeDER()
+ *
+ * @package ASN1
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class Element
+{
+ /**
+ * Raw element value
+ *
+ * @var string
+ * @access private
+ */
+ var $element;
+
+ /**
+ * Constructor
+ *
+ * @param string $encoded
+ * @return \phpseclib\File\ASN1\Element
+ * @access public
+ */
+ function __construct($encoded)
+ {
+ $this->element = $encoded;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP X.509 Parser
+ *
+ * PHP version 5
+ *
+ * Encode and decode X.509 certificates.
+ *
+ * The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and
+ * {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}.
+ *
+ * Note that loading an X.509 certificate and resaving it may invalidate the signature. The reason being that the signature is based on a
+ * portion of the certificate that contains optional parameters with default values. ie. if the parameter isn't there the default value is
+ * used. Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can
+ * be encoded. It can be encoded explicitly or left out all together. This would effect the signature value and thus may invalidate the
+ * the certificate all together unless the certificate is re-signed.
+ *
+ * @category File
+ * @package X509
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2012 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\File;
+
+use phpseclib\Crypt\Hash;
+use phpseclib\Crypt\Random;
+use phpseclib\Crypt\RSA;
+use phpseclib\File\ASN1\Element;
+use phpseclib\Math\BigInteger;
+use DateTime;
+use DateTimeZone;
+
+/**
+ * Pure-PHP X.509 Parser
+ *
+ * @package X509
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class X509
+{
+ /**
+ * Flag to only accept signatures signed by certificate authorities
+ *
+ * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
+ *
+ * @access public
+ */
+ const VALIDATE_SIGNATURE_BY_CA = 1;
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\File\X509::getDN()
+ */
+ /**
+ * Return internal array representation
+ */
+ const DN_ARRAY = 0;
+ /**
+ * Return string
+ */
+ const DN_STRING = 1;
+ /**
+ * Return ASN.1 name string
+ */
+ const DN_ASN1 = 2;
+ /**
+ * Return OpenSSL compatible array
+ */
+ const DN_OPENSSL = 3;
+ /**
+ * Return canonical ASN.1 RDNs string
+ */
+ const DN_CANON = 4;
+ /**
+ * Return name hash for file indexing
+ */
+ const DN_HASH = 5;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\File\X509::saveX509()
+ * @see \phpseclib\File\X509::saveCSR()
+ * @see \phpseclib\File\X509::saveCRL()
+ */
+ /**
+ * Save as PEM
+ *
+ * ie. a base64-encoded PEM with a header and a footer
+ */
+ const FORMAT_PEM = 0;
+ /**
+ * Save as DER
+ */
+ const FORMAT_DER = 1;
+ /**
+ * Save as a SPKAC
+ *
+ * Only works on CSRs. Not currently supported.
+ */
+ const FORMAT_SPKAC = 2;
+ /**
+ * Auto-detect the format
+ *
+ * Used only by the load*() functions
+ */
+ const FORMAT_AUTO_DETECT = 3;
+ /**#@-*/
+
+ /**
+ * Attribute value disposition.
+ * If disposition is >= 0, this is the index of the target value.
+ */
+ const ATTR_ALL = -1; // All attribute values (array).
+ const ATTR_APPEND = -2; // Add a value.
+ const ATTR_REPLACE = -3; // Clear first, then add a value.
+
+ /**
+ * ASN.1 syntax for X.509 certificates
+ *
+ * @var array
+ * @access private
+ */
+ var $Certificate;
+
+ /**#@+
+ * ASN.1 syntax for various extensions
+ *
+ * @access private
+ */
+ var $DirectoryString;
+ var $PKCS9String;
+ var $AttributeValue;
+ var $Extensions;
+ var $KeyUsage;
+ var $ExtKeyUsageSyntax;
+ var $BasicConstraints;
+ var $KeyIdentifier;
+ var $CRLDistributionPoints;
+ var $AuthorityKeyIdentifier;
+ var $CertificatePolicies;
+ var $AuthorityInfoAccessSyntax;
+ var $SubjectAltName;
+ var $SubjectDirectoryAttributes;
+ var $PrivateKeyUsagePeriod;
+ var $IssuerAltName;
+ var $PolicyMappings;
+ var $NameConstraints;
+
+ var $CPSuri;
+ var $UserNotice;
+
+ var $netscape_cert_type;
+ var $netscape_comment;
+ var $netscape_ca_policy_url;
+
+ var $Name;
+ var $RelativeDistinguishedName;
+ var $CRLNumber;
+ var $CRLReason;
+ var $IssuingDistributionPoint;
+ var $InvalidityDate;
+ var $CertificateIssuer;
+ var $HoldInstructionCode;
+ var $SignedPublicKeyAndChallenge;
+ /**#@-*/
+
+ /**#@+
+ * ASN.1 syntax for various DN attributes
+ *
+ * @access private
+ */
+ var $PostalAddress;
+ /**#@-*/
+
+ /**
+ * ASN.1 syntax for Certificate Signing Requests (RFC2986)
+ *
+ * @var array
+ * @access private
+ */
+ var $CertificationRequest;
+
+ /**
+ * ASN.1 syntax for Certificate Revocation Lists (RFC5280)
+ *
+ * @var array
+ * @access private
+ */
+ var $CertificateList;
+
+ /**
+ * Distinguished Name
+ *
+ * @var array
+ * @access private
+ */
+ var $dn;
+
+ /**
+ * Public key
+ *
+ * @var string
+ * @access private
+ */
+ var $publicKey;
+
+ /**
+ * Private key
+ *
+ * @var string
+ * @access private
+ */
+ var $privateKey;
+
+ /**
+ * Object identifiers for X.509 certificates
+ *
+ * @var array
+ * @access private
+ * @link http://en.wikipedia.org/wiki/Object_identifier
+ */
+ var $oids;
+
+ /**
+ * The certificate authorities
+ *
+ * @var array
+ * @access private
+ */
+ var $CAs;
+
+ /**
+ * The currently loaded certificate
+ *
+ * @var array
+ * @access private
+ */
+ var $currentCert;
+
+ /**
+ * The signature subject
+ *
+ * There's no guarantee \phpseclib\File\X509 is going to re-encode an X.509 cert in the same way it was originally
+ * encoded so we take save the portion of the original cert that the signature would have made for.
+ *
+ * @var string
+ * @access private
+ */
+ var $signatureSubject;
+
+ /**
+ * Certificate Start Date
+ *
+ * @var string
+ * @access private
+ */
+ var $startDate;
+
+ /**
+ * Certificate End Date
+ *
+ * @var string
+ * @access private
+ */
+ var $endDate;
+
+ /**
+ * Serial Number
+ *
+ * @var string
+ * @access private
+ */
+ var $serialNumber;
+
+ /**
+ * Key Identifier
+ *
+ * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
+ * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
+ *
+ * @var string
+ * @access private
+ */
+ var $currentKeyIdentifier;
+
+ /**
+ * CA Flag
+ *
+ * @var bool
+ * @access private
+ */
+ var $caFlag = false;
+
+ /**
+ * SPKAC Challenge
+ *
+ * @var string
+ * @access private
+ */
+ var $challenge;
+
+ /**
+ * Recursion Limit
+ *
+ * @var int
+ * @access private
+ */
+ static $recur_limit = 5;
+
+ /**
+ * URL fetch flag
+ *
+ * @var bool
+ * @access private
+ */
+ static $disable_url_fetch = false;
+
+ /**
+ * Default Constructor.
+ *
+ * @return \phpseclib\File\X509
+ * @access public
+ */
+ function __construct()
+ {
+ // Explicitly Tagged Module, 1988 Syntax
+ // http://tools.ietf.org/html/rfc5280#appendix-A.1
+
+ $this->DirectoryString = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'teletexString' => array('type' => ASN1::TYPE_TELETEX_STRING),
+ 'printableString' => array('type' => ASN1::TYPE_PRINTABLE_STRING),
+ 'universalString' => array('type' => ASN1::TYPE_UNIVERSAL_STRING),
+ 'utf8String' => array('type' => ASN1::TYPE_UTF8_STRING),
+ 'bmpString' => array('type' => ASN1::TYPE_BMP_STRING)
+ )
+ );
+
+ $this->PKCS9String = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'ia5String' => array('type' => ASN1::TYPE_IA5_STRING),
+ 'directoryString' => $this->DirectoryString
+ )
+ );
+
+ $this->AttributeValue = array('type' => ASN1::TYPE_ANY);
+
+ $AttributeType = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
+
+ $AttributeTypeAndValue = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'type' => $AttributeType,
+ 'value'=> $this->AttributeValue
+ )
+ );
+
+ /*
+ In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
+ but they can be useful at times when either there is no unique attribute in the entry or you
+ want to ensure that the entry's DN contains some useful identifying information.
+
+ - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
+ */
+ $this->RelativeDistinguishedName = array(
+ 'type' => ASN1::TYPE_SET,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $AttributeTypeAndValue
+ );
+
+ // http://tools.ietf.org/html/rfc5280#section-4.1.2.4
+ $RDNSequence = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ // RDNSequence does not define a min or a max, which means it doesn't have one
+ 'min' => 0,
+ 'max' => -1,
+ 'children' => $this->RelativeDistinguishedName
+ );
+
+ $this->Name = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'rdnSequence' => $RDNSequence
+ )
+ );
+
+ // http://tools.ietf.org/html/rfc5280#section-4.1.1.2
+ $AlgorithmIdentifier = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'algorithm' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
+ 'parameters' => array(
+ 'type' => ASN1::TYPE_ANY,
+ 'optional' => true
+ )
+ )
+ );
+
+ /*
+ A certificate using system MUST reject the certificate if it encounters
+ a critical extension it does not recognize; however, a non-critical
+ extension may be ignored if it is not recognized.
+
+ http://tools.ietf.org/html/rfc5280#section-4.2
+ */
+ $Extension = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'extnId' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
+ 'critical' => array(
+ 'type' => ASN1::TYPE_BOOLEAN,
+ 'optional' => true,
+ 'default' => false
+ ),
+ 'extnValue' => array('type' => ASN1::TYPE_OCTET_STRING)
+ )
+ );
+
+ $this->Extensions = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ // technically, it's MAX, but we'll assume anything < 0 is MAX
+ 'max' => -1,
+ // if 'children' isn't an array then 'min' and 'max' must be defined
+ 'children' => $Extension
+ );
+
+ $SubjectPublicKeyInfo = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'algorithm' => $AlgorithmIdentifier,
+ 'subjectPublicKey' => array('type' => ASN1::TYPE_BIT_STRING)
+ )
+ );
+
+ $UniqueIdentifier = array('type' => ASN1::TYPE_BIT_STRING);
+
+ $Time = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'utcTime' => array('type' => ASN1::TYPE_UTC_TIME),
+ 'generalTime' => array('type' => ASN1::TYPE_GENERALIZED_TIME)
+ )
+ );
+
+ // http://tools.ietf.org/html/rfc5280#section-4.1.2.5
+ $Validity = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'notBefore' => $Time,
+ 'notAfter' => $Time
+ )
+ );
+
+ $CertificateSerialNumber = array('type' => ASN1::TYPE_INTEGER);
+
+ $Version = array(
+ 'type' => ASN1::TYPE_INTEGER,
+ 'mapping' => array('v1', 'v2', 'v3')
+ );
+
+ // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
+ $TBSCertificate = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ // technically, default implies optional, but we'll define it as being optional, none-the-less, just to
+ // reenforce that fact
+ 'version' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'explicit' => true,
+ 'default' => 'v1'
+ ) + $Version,
+ 'serialNumber' => $CertificateSerialNumber,
+ 'signature' => $AlgorithmIdentifier,
+ 'issuer' => $this->Name,
+ 'validity' => $Validity,
+ 'subject' => $this->Name,
+ 'subjectPublicKeyInfo' => $SubjectPublicKeyInfo,
+ // implicit means that the T in the TLV structure is to be rewritten, regardless of the type
+ 'issuerUniqueID' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $UniqueIdentifier,
+ 'subjectUniqueID' => array(
+ 'constant' => 2,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $UniqueIdentifier,
+ // <http://tools.ietf.org/html/rfc2459#page-74> doesn't use the EXPLICIT keyword but if
+ // it's not IMPLICIT, it's EXPLICIT
+ 'extensions' => array(
+ 'constant' => 3,
+ 'optional' => true,
+ 'explicit' => true
+ ) + $this->Extensions
+ )
+ );
+
+ $this->Certificate = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'tbsCertificate' => $TBSCertificate,
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
+ 'signature' => array('type' => ASN1::TYPE_BIT_STRING)
+ )
+ );
+
+ $this->KeyUsage = array(
+ 'type' => ASN1::TYPE_BIT_STRING,
+ 'mapping' => array(
+ 'digitalSignature',
+ 'nonRepudiation',
+ 'keyEncipherment',
+ 'dataEncipherment',
+ 'keyAgreement',
+ 'keyCertSign',
+ 'cRLSign',
+ 'encipherOnly',
+ 'decipherOnly'
+ )
+ );
+
+ $this->BasicConstraints = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'cA' => array(
+ 'type' => ASN1::TYPE_BOOLEAN,
+ 'optional' => true,
+ 'default' => false
+ ),
+ 'pathLenConstraint' => array(
+ 'type' => ASN1::TYPE_INTEGER,
+ 'optional' => true
+ )
+ )
+ );
+
+ $this->KeyIdentifier = array('type' => ASN1::TYPE_OCTET_STRING);
+
+ $OrganizationalUnitNames = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => 4, // ub-organizational-units
+ 'children' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
+ );
+
+ $PersonalName = array(
+ 'type' => ASN1::TYPE_SET,
+ 'children' => array(
+ 'surname' => array(
+ 'type' => ASN1::TYPE_PRINTABLE_STRING,
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'given-name' => array(
+ 'type' => ASN1::TYPE_PRINTABLE_STRING,
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'initials' => array(
+ 'type' => ASN1::TYPE_PRINTABLE_STRING,
+ 'constant' => 2,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'generation-qualifier' => array(
+ 'type' => ASN1::TYPE_PRINTABLE_STRING,
+ 'constant' => 3,
+ 'optional' => true,
+ 'implicit' => true
+ )
+ )
+ );
+
+ $NumericUserIdentifier = array('type' => ASN1::TYPE_NUMERIC_STRING);
+
+ $OrganizationName = array('type' => ASN1::TYPE_PRINTABLE_STRING);
+
+ $PrivateDomainName = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'numeric' => array('type' => ASN1::TYPE_NUMERIC_STRING),
+ 'printable' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
+ )
+ );
+
+ $TerminalIdentifier = array('type' => ASN1::TYPE_PRINTABLE_STRING);
+
+ $NetworkAddress = array('type' => ASN1::TYPE_NUMERIC_STRING);
+
+ $AdministrationDomainName = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ // if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or
+ // (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC
+ 'class' => ASN1::CLASS_APPLICATION,
+ 'cast' => 2,
+ 'children' => array(
+ 'numeric' => array('type' => ASN1::TYPE_NUMERIC_STRING),
+ 'printable' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
+ )
+ );
+
+ $CountryName = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ // if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or
+ // (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC
+ 'class' => ASN1::CLASS_APPLICATION,
+ 'cast' => 1,
+ 'children' => array(
+ 'x121-dcc-code' => array('type' => ASN1::TYPE_NUMERIC_STRING),
+ 'iso-3166-alpha2-code' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
+ )
+ );
+
+ $AnotherName = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'type-id' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
+ 'value' => array(
+ 'type' => ASN1::TYPE_ANY,
+ 'constant' => 0,
+ 'optional' => true,
+ 'explicit' => true
+ )
+ )
+ );
+
+ $ExtensionAttribute = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'extension-attribute-type' => array(
+ 'type' => ASN1::TYPE_PRINTABLE_STRING,
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'extension-attribute-value' => array(
+ 'type' => ASN1::TYPE_ANY,
+ 'constant' => 1,
+ 'optional' => true,
+ 'explicit' => true
+ )
+ )
+ );
+
+ $ExtensionAttributes = array(
+ 'type' => ASN1::TYPE_SET,
+ 'min' => 1,
+ 'max' => 256, // ub-extension-attributes
+ 'children' => $ExtensionAttribute
+ );
+
+ $BuiltInDomainDefinedAttribute = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'type' => array('type' => ASN1::TYPE_PRINTABLE_STRING),
+ 'value' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
+ )
+ );
+
+ $BuiltInDomainDefinedAttributes = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => 4, // ub-domain-defined-attributes
+ 'children' => $BuiltInDomainDefinedAttribute
+ );
+
+ $BuiltInStandardAttributes = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'country-name' => array('optional' => true) + $CountryName,
+ 'administration-domain-name' => array('optional' => true) + $AdministrationDomainName,
+ 'network-address' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $NetworkAddress,
+ 'terminal-identifier' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $TerminalIdentifier,
+ 'private-domain-name' => array(
+ 'constant' => 2,
+ 'optional' => true,
+ 'explicit' => true
+ ) + $PrivateDomainName,
+ 'organization-name' => array(
+ 'constant' => 3,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $OrganizationName,
+ 'numeric-user-identifier' => array(
+ 'constant' => 4,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $NumericUserIdentifier,
+ 'personal-name' => array(
+ 'constant' => 5,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $PersonalName,
+ 'organizational-unit-names' => array(
+ 'constant' => 6,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $OrganizationalUnitNames
+ )
+ );
+
+ $ORAddress = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'built-in-standard-attributes' => $BuiltInStandardAttributes,
+ 'built-in-domain-defined-attributes' => array('optional' => true) + $BuiltInDomainDefinedAttributes,
+ 'extension-attributes' => array('optional' => true) + $ExtensionAttributes
+ )
+ );
+
+ $EDIPartyName = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'nameAssigner' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $this->DirectoryString,
+ // partyName is technically required but \phpseclib\File\ASN1 doesn't currently support non-optional constants and
+ // setting it to optional gets the job done in any event.
+ 'partyName' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $this->DirectoryString
+ )
+ );
+
+ $GeneralName = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'otherName' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $AnotherName,
+ 'rfc822Name' => array(
+ 'type' => ASN1::TYPE_IA5_STRING,
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'dNSName' => array(
+ 'type' => ASN1::TYPE_IA5_STRING,
+ 'constant' => 2,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'x400Address' => array(
+ 'constant' => 3,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $ORAddress,
+ 'directoryName' => array(
+ 'constant' => 4,
+ 'optional' => true,
+ 'explicit' => true
+ ) + $this->Name,
+ 'ediPartyName' => array(
+ 'constant' => 5,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $EDIPartyName,
+ 'uniformResourceIdentifier' => array(
+ 'type' => ASN1::TYPE_IA5_STRING,
+ 'constant' => 6,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'iPAddress' => array(
+ 'type' => ASN1::TYPE_OCTET_STRING,
+ 'constant' => 7,
+ 'optional' => true,
+ 'implicit' => true
+ ),
+ 'registeredID' => array(
+ 'type' => ASN1::TYPE_OBJECT_IDENTIFIER,
+ 'constant' => 8,
+ 'optional' => true,
+ 'implicit' => true
+ )
+ )
+ );
+
+ $GeneralNames = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $GeneralName
+ );
+
+ $this->IssuerAltName = $GeneralNames;
+
+ $ReasonFlags = array(
+ 'type' => ASN1::TYPE_BIT_STRING,
+ 'mapping' => array(
+ 'unused',
+ 'keyCompromise',
+ 'cACompromise',
+ 'affiliationChanged',
+ 'superseded',
+ 'cessationOfOperation',
+ 'certificateHold',
+ 'privilegeWithdrawn',
+ 'aACompromise'
+ )
+ );
+
+ $DistributionPointName = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'fullName' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $GeneralNames,
+ 'nameRelativeToCRLIssuer' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $this->RelativeDistinguishedName
+ )
+ );
+
+ $DistributionPoint = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'distributionPoint' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'explicit' => true
+ ) + $DistributionPointName,
+ 'reasons' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $ReasonFlags,
+ 'cRLIssuer' => array(
+ 'constant' => 2,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $GeneralNames
+ )
+ );
+
+ $this->CRLDistributionPoints = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $DistributionPoint
+ );
+
+ $this->AuthorityKeyIdentifier = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'keyIdentifier' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $this->KeyIdentifier,
+ 'authorityCertIssuer' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $GeneralNames,
+ 'authorityCertSerialNumber' => array(
+ 'constant' => 2,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $CertificateSerialNumber
+ )
+ );
+
+ $PolicyQualifierId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
+
+ $PolicyQualifierInfo = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'policyQualifierId' => $PolicyQualifierId,
+ 'qualifier' => array('type' => ASN1::TYPE_ANY)
+ )
+ );
+
+ $CertPolicyId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
+
+ $PolicyInformation = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'policyIdentifier' => $CertPolicyId,
+ 'policyQualifiers' => array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 0,
+ 'max' => -1,
+ 'optional' => true,
+ 'children' => $PolicyQualifierInfo
+ )
+ )
+ );
+
+ $this->CertificatePolicies = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $PolicyInformation
+ );
+
+ $this->PolicyMappings = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'issuerDomainPolicy' => $CertPolicyId,
+ 'subjectDomainPolicy' => $CertPolicyId
+ )
+ )
+ );
+
+ $KeyPurposeId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
+
+ $this->ExtKeyUsageSyntax = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $KeyPurposeId
+ );
+
+ $AccessDescription = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'accessMethod' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
+ 'accessLocation' => $GeneralName
+ )
+ );
+
+ $this->AuthorityInfoAccessSyntax = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $AccessDescription
+ );
+
+ $this->SubjectAltName = $GeneralNames;
+
+ $this->PrivateKeyUsagePeriod = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'notBefore' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true,
+ 'type' => ASN1::TYPE_GENERALIZED_TIME),
+ 'notAfter' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true,
+ 'type' => ASN1::TYPE_GENERALIZED_TIME)
+ )
+ );
+
+ $BaseDistance = array('type' => ASN1::TYPE_INTEGER);
+
+ $GeneralSubtree = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'base' => $GeneralName,
+ 'minimum' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true,
+ 'default' => new BigInteger(0)
+ ) + $BaseDistance,
+ 'maximum' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true,
+ ) + $BaseDistance
+ )
+ );
+
+ $GeneralSubtrees = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $GeneralSubtree
+ );
+
+ $this->NameConstraints = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'permittedSubtrees' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $GeneralSubtrees,
+ 'excludedSubtrees' => array(
+ 'constant' => 1,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $GeneralSubtrees
+ )
+ );
+
+ $this->CPSuri = array('type' => ASN1::TYPE_IA5_STRING);
+
+ $DisplayText = array(
+ 'type' => ASN1::TYPE_CHOICE,
+ 'children' => array(
+ 'ia5String' => array('type' => ASN1::TYPE_IA5_STRING),
+ 'visibleString' => array('type' => ASN1::TYPE_VISIBLE_STRING),
+ 'bmpString' => array('type' => ASN1::TYPE_BMP_STRING),
+ 'utf8String' => array('type' => ASN1::TYPE_UTF8_STRING)
+ )
+ );
+
+ $NoticeReference = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'organization' => $DisplayText,
+ 'noticeNumbers' => array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => 200,
+ 'children' => array('type' => ASN1::TYPE_INTEGER)
+ )
+ )
+ );
+
+ $this->UserNotice = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'noticeRef' => array(
+ 'optional' => true,
+ 'implicit' => true
+ ) + $NoticeReference,
+ 'explicitText' => array(
+ 'optional' => true,
+ 'implicit' => true
+ ) + $DisplayText
+ )
+ );
+
+ // mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
+ $this->netscape_cert_type = array(
+ 'type' => ASN1::TYPE_BIT_STRING,
+ 'mapping' => array(
+ 'SSLClient',
+ 'SSLServer',
+ 'Email',
+ 'ObjectSigning',
+ 'Reserved',
+ 'SSLCA',
+ 'EmailCA',
+ 'ObjectSigningCA'
+ )
+ );
+
+ $this->netscape_comment = array('type' => ASN1::TYPE_IA5_STRING);
+ $this->netscape_ca_policy_url = array('type' => ASN1::TYPE_IA5_STRING);
+
+ // attribute is used in RFC2986 but we're using the RFC5280 definition
+
+ $Attribute = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'type' => $AttributeType,
+ 'value'=> array(
+ 'type' => ASN1::TYPE_SET,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $this->AttributeValue
+ )
+ )
+ );
+
+ $this->SubjectDirectoryAttributes = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $Attribute
+ );
+
+ // adapted from <http://tools.ietf.org/html/rfc2986>
+
+ $Attributes = array(
+ 'type' => ASN1::TYPE_SET,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $Attribute
+ );
+
+ $CertificationRequestInfo = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'version' => array(
+ 'type' => ASN1::TYPE_INTEGER,
+ 'mapping' => array('v1')
+ ),
+ 'subject' => $this->Name,
+ 'subjectPKInfo' => $SubjectPublicKeyInfo,
+ 'attributes' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $Attributes,
+ )
+ );
+
+ $this->CertificationRequest = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'certificationRequestInfo' => $CertificationRequestInfo,
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
+ 'signature' => array('type' => ASN1::TYPE_BIT_STRING)
+ )
+ );
+
+ $RevokedCertificate = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'userCertificate' => $CertificateSerialNumber,
+ 'revocationDate' => $Time,
+ 'crlEntryExtensions' => array(
+ 'optional' => true
+ ) + $this->Extensions
+ )
+ );
+
+ $TBSCertList = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'version' => array(
+ 'optional' => true,
+ 'default' => 'v1'
+ ) + $Version,
+ 'signature' => $AlgorithmIdentifier,
+ 'issuer' => $this->Name,
+ 'thisUpdate' => $Time,
+ 'nextUpdate' => array(
+ 'optional' => true
+ ) + $Time,
+ 'revokedCertificates' => array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'optional' => true,
+ 'min' => 0,
+ 'max' => -1,
+ 'children' => $RevokedCertificate
+ ),
+ 'crlExtensions' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'explicit' => true
+ ) + $this->Extensions
+ )
+ );
+
+ $this->CertificateList = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'tbsCertList' => $TBSCertList,
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
+ 'signature' => array('type' => ASN1::TYPE_BIT_STRING)
+ )
+ );
+
+ $this->CRLNumber = array('type' => ASN1::TYPE_INTEGER);
+
+ $this->CRLReason = array('type' => ASN1::TYPE_ENUMERATED,
+ 'mapping' => array(
+ 'unspecified',
+ 'keyCompromise',
+ 'cACompromise',
+ 'affiliationChanged',
+ 'superseded',
+ 'cessationOfOperation',
+ 'certificateHold',
+ // Value 7 is not used.
+ 8 => 'removeFromCRL',
+ 'privilegeWithdrawn',
+ 'aACompromise'
+ )
+ );
+
+ $this->IssuingDistributionPoint = array('type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'distributionPoint' => array(
+ 'constant' => 0,
+ 'optional' => true,
+ 'explicit' => true
+ ) + $DistributionPointName,
+ 'onlyContainsUserCerts' => array(
+ 'type' => ASN1::TYPE_BOOLEAN,
+ 'constant' => 1,
+ 'optional' => true,
+ 'default' => false,
+ 'implicit' => true
+ ),
+ 'onlyContainsCACerts' => array(
+ 'type' => ASN1::TYPE_BOOLEAN,
+ 'constant' => 2,
+ 'optional' => true,
+ 'default' => false,
+ 'implicit' => true
+ ),
+ 'onlySomeReasons' => array(
+ 'constant' => 3,
+ 'optional' => true,
+ 'implicit' => true
+ ) + $ReasonFlags,
+ 'indirectCRL' => array(
+ 'type' => ASN1::TYPE_BOOLEAN,
+ 'constant' => 4,
+ 'optional' => true,
+ 'default' => false,
+ 'implicit' => true
+ ),
+ 'onlyContainsAttributeCerts' => array(
+ 'type' => ASN1::TYPE_BOOLEAN,
+ 'constant' => 5,
+ 'optional' => true,
+ 'default' => false,
+ 'implicit' => true
+ )
+ )
+ );
+
+ $this->InvalidityDate = array('type' => ASN1::TYPE_GENERALIZED_TIME);
+
+ $this->CertificateIssuer = $GeneralNames;
+
+ $this->HoldInstructionCode = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
+
+ $PublicKeyAndChallenge = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'spki' => $SubjectPublicKeyInfo,
+ 'challenge' => array('type' => ASN1::TYPE_IA5_STRING)
+ )
+ );
+
+ $this->SignedPublicKeyAndChallenge = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'children' => array(
+ 'publicKeyAndChallenge' => $PublicKeyAndChallenge,
+ 'signatureAlgorithm' => $AlgorithmIdentifier,
+ 'signature' => array('type' => ASN1::TYPE_BIT_STRING)
+ )
+ );
+
+ $this->PostalAddress = array(
+ 'type' => ASN1::TYPE_SEQUENCE,
+ 'optional' => true,
+ 'min' => 1,
+ 'max' => -1,
+ 'children' => $this->DirectoryString
+ );
+
+ // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
+ $this->oids = array(
+ '1.3.6.1.5.5.7' => 'id-pkix',
+ '1.3.6.1.5.5.7.1' => 'id-pe',
+ '1.3.6.1.5.5.7.2' => 'id-qt',
+ '1.3.6.1.5.5.7.3' => 'id-kp',
+ '1.3.6.1.5.5.7.48' => 'id-ad',
+ '1.3.6.1.5.5.7.2.1' => 'id-qt-cps',
+ '1.3.6.1.5.5.7.2.2' => 'id-qt-unotice',
+ '1.3.6.1.5.5.7.48.1' =>'id-ad-ocsp',
+ '1.3.6.1.5.5.7.48.2' => 'id-ad-caIssuers',
+ '1.3.6.1.5.5.7.48.3' => 'id-ad-timeStamping',
+ '1.3.6.1.5.5.7.48.5' => 'id-ad-caRepository',
+ '2.5.4' => 'id-at',
+ '2.5.4.41' => 'id-at-name',
+ '2.5.4.4' => 'id-at-surname',
+ '2.5.4.42' => 'id-at-givenName',
+ '2.5.4.43' => 'id-at-initials',
+ '2.5.4.44' => 'id-at-generationQualifier',
+ '2.5.4.3' => 'id-at-commonName',
+ '2.5.4.7' => 'id-at-localityName',
+ '2.5.4.8' => 'id-at-stateOrProvinceName',
+ '2.5.4.10' => 'id-at-organizationName',
+ '2.5.4.11' => 'id-at-organizationalUnitName',
+ '2.5.4.12' => 'id-at-title',
+ '2.5.4.13' => 'id-at-description',
+ '2.5.4.46' => 'id-at-dnQualifier',
+ '2.5.4.6' => 'id-at-countryName',
+ '2.5.4.5' => 'id-at-serialNumber',
+ '2.5.4.65' => 'id-at-pseudonym',
+ '2.5.4.17' => 'id-at-postalCode',
+ '2.5.4.9' => 'id-at-streetAddress',
+ '2.5.4.45' => 'id-at-uniqueIdentifier',
+ '2.5.4.72' => 'id-at-role',
+ '2.5.4.16' => 'id-at-postalAddress',
+
+ '0.9.2342.19200300.100.1.25' => 'id-domainComponent',
+ '1.2.840.113549.1.9' => 'pkcs-9',
+ '1.2.840.113549.1.9.1' => 'pkcs-9-at-emailAddress',
+ '2.5.29' => 'id-ce',
+ '2.5.29.35' => 'id-ce-authorityKeyIdentifier',
+ '2.5.29.14' => 'id-ce-subjectKeyIdentifier',
+ '2.5.29.15' => 'id-ce-keyUsage',
+ '2.5.29.16' => 'id-ce-privateKeyUsagePeriod',
+ '2.5.29.32' => 'id-ce-certificatePolicies',
+ '2.5.29.32.0' => 'anyPolicy',
+
+ '2.5.29.33' => 'id-ce-policyMappings',
+ '2.5.29.17' => 'id-ce-subjectAltName',
+ '2.5.29.18' => 'id-ce-issuerAltName',
+ '2.5.29.9' => 'id-ce-subjectDirectoryAttributes',
+ '2.5.29.19' => 'id-ce-basicConstraints',
+ '2.5.29.30' => 'id-ce-nameConstraints',
+ '2.5.29.36' => 'id-ce-policyConstraints',
+ '2.5.29.31' => 'id-ce-cRLDistributionPoints',
+ '2.5.29.37' => 'id-ce-extKeyUsage',
+ '2.5.29.37.0' => 'anyExtendedKeyUsage',
+ '1.3.6.1.5.5.7.3.1' => 'id-kp-serverAuth',
+ '1.3.6.1.5.5.7.3.2' => 'id-kp-clientAuth',
+ '1.3.6.1.5.5.7.3.3' => 'id-kp-codeSigning',
+ '1.3.6.1.5.5.7.3.4' => 'id-kp-emailProtection',
+ '1.3.6.1.5.5.7.3.8' => 'id-kp-timeStamping',
+ '1.3.6.1.5.5.7.3.9' => 'id-kp-OCSPSigning',
+ '2.5.29.54' => 'id-ce-inhibitAnyPolicy',
+ '2.5.29.46' => 'id-ce-freshestCRL',
+ '1.3.6.1.5.5.7.1.1' => 'id-pe-authorityInfoAccess',
+ '1.3.6.1.5.5.7.1.11' => 'id-pe-subjectInfoAccess',
+ '2.5.29.20' => 'id-ce-cRLNumber',
+ '2.5.29.28' => 'id-ce-issuingDistributionPoint',
+ '2.5.29.27' => 'id-ce-deltaCRLIndicator',
+ '2.5.29.21' => 'id-ce-cRLReasons',
+ '2.5.29.29' => 'id-ce-certificateIssuer',
+ '2.5.29.23' => 'id-ce-holdInstructionCode',
+ '1.2.840.10040.2' => 'holdInstruction',
+ '1.2.840.10040.2.1' => 'id-holdinstruction-none',
+ '1.2.840.10040.2.2' => 'id-holdinstruction-callissuer',
+ '1.2.840.10040.2.3' => 'id-holdinstruction-reject',
+ '2.5.29.24' => 'id-ce-invalidityDate',
+
+ '1.2.840.113549.2.2' => 'md2',
+ '1.2.840.113549.2.5' => 'md5',
+ '1.3.14.3.2.26' => 'id-sha1',
+ '1.2.840.10040.4.1' => 'id-dsa',
+ '1.2.840.10040.4.3' => 'id-dsa-with-sha1',
+ '1.2.840.113549.1.1' => 'pkcs-1',
+ '1.2.840.113549.1.1.1' => 'rsaEncryption',
+ '1.2.840.113549.1.1.2' => 'md2WithRSAEncryption',
+ '1.2.840.113549.1.1.4' => 'md5WithRSAEncryption',
+ '1.2.840.113549.1.1.5' => 'sha1WithRSAEncryption',
+ '1.2.840.10046.2.1' => 'dhpublicnumber',
+ '2.16.840.1.101.2.1.1.22' => 'id-keyExchangeAlgorithm',
+ '1.2.840.10045' => 'ansi-X9-62',
+ '1.2.840.10045.4' => 'id-ecSigType',
+ '1.2.840.10045.4.1' => 'ecdsa-with-SHA1',
+ '1.2.840.10045.1' => 'id-fieldType',
+ '1.2.840.10045.1.1' => 'prime-field',
+ '1.2.840.10045.1.2' => 'characteristic-two-field',
+ '1.2.840.10045.1.2.3' => 'id-characteristic-two-basis',
+ '1.2.840.10045.1.2.3.1' => 'gnBasis',
+ '1.2.840.10045.1.2.3.2' => 'tpBasis',
+ '1.2.840.10045.1.2.3.3' => 'ppBasis',
+ '1.2.840.10045.2' => 'id-publicKeyType',
+ '1.2.840.10045.2.1' => 'id-ecPublicKey',
+ '1.2.840.10045.3' => 'ellipticCurve',
+ '1.2.840.10045.3.0' => 'c-TwoCurve',
+ '1.2.840.10045.3.0.1' => 'c2pnb163v1',
+ '1.2.840.10045.3.0.2' => 'c2pnb163v2',
+ '1.2.840.10045.3.0.3' => 'c2pnb163v3',
+ '1.2.840.10045.3.0.4' => 'c2pnb176w1',
+ '1.2.840.10045.3.0.5' => 'c2pnb191v1',
+ '1.2.840.10045.3.0.6' => 'c2pnb191v2',
+ '1.2.840.10045.3.0.7' => 'c2pnb191v3',
+ '1.2.840.10045.3.0.8' => 'c2pnb191v4',
+ '1.2.840.10045.3.0.9' => 'c2pnb191v5',
+ '1.2.840.10045.3.0.10' => 'c2pnb208w1',
+ '1.2.840.10045.3.0.11' => 'c2pnb239v1',
+ '1.2.840.10045.3.0.12' => 'c2pnb239v2',
+ '1.2.840.10045.3.0.13' => 'c2pnb239v3',
+ '1.2.840.10045.3.0.14' => 'c2pnb239v4',
+ '1.2.840.10045.3.0.15' => 'c2pnb239v5',
+ '1.2.840.10045.3.0.16' => 'c2pnb272w1',
+ '1.2.840.10045.3.0.17' => 'c2pnb304w1',
+ '1.2.840.10045.3.0.18' => 'c2pnb359v1',
+ '1.2.840.10045.3.0.19' => 'c2pnb368w1',
+ '1.2.840.10045.3.0.20' => 'c2pnb431r1',
+ '1.2.840.10045.3.1' => 'primeCurve',
+ '1.2.840.10045.3.1.1' => 'prime192v1',
+ '1.2.840.10045.3.1.2' => 'prime192v2',
+ '1.2.840.10045.3.1.3' => 'prime192v3',
+ '1.2.840.10045.3.1.4' => 'prime239v1',
+ '1.2.840.10045.3.1.5' => 'prime239v2',
+ '1.2.840.10045.3.1.6' => 'prime239v3',
+ '1.2.840.10045.3.1.7' => 'prime256v1',
+ '1.2.840.113549.1.1.7' => 'id-RSAES-OAEP',
+ '1.2.840.113549.1.1.9' => 'id-pSpecified',
+ '1.2.840.113549.1.1.10' => 'id-RSASSA-PSS',
+ '1.2.840.113549.1.1.8' => 'id-mgf1',
+ '1.2.840.113549.1.1.14' => 'sha224WithRSAEncryption',
+ '1.2.840.113549.1.1.11' => 'sha256WithRSAEncryption',
+ '1.2.840.113549.1.1.12' => 'sha384WithRSAEncryption',
+ '1.2.840.113549.1.1.13' => 'sha512WithRSAEncryption',
+ '2.16.840.1.101.3.4.2.4' => 'id-sha224',
+ '2.16.840.1.101.3.4.2.1' => 'id-sha256',
+ '2.16.840.1.101.3.4.2.2' => 'id-sha384',
+ '2.16.840.1.101.3.4.2.3' => 'id-sha512',
+ '1.2.643.2.2.4' => 'id-GostR3411-94-with-GostR3410-94',
+ '1.2.643.2.2.3' => 'id-GostR3411-94-with-GostR3410-2001',
+ '1.2.643.2.2.20' => 'id-GostR3410-2001',
+ '1.2.643.2.2.19' => 'id-GostR3410-94',
+ // Netscape Object Identifiers from "Netscape Certificate Extensions"
+ '2.16.840.1.113730' => 'netscape',
+ '2.16.840.1.113730.1' => 'netscape-cert-extension',
+ '2.16.840.1.113730.1.1' => 'netscape-cert-type',
+ '2.16.840.1.113730.1.13' => 'netscape-comment',
+ '2.16.840.1.113730.1.8' => 'netscape-ca-policy-url',
+ // the following are X.509 extensions not supported by phpseclib
+ '1.3.6.1.5.5.7.1.12' => 'id-pe-logotype',
+ '1.2.840.113533.7.65.0' => 'entrustVersInfo',
+ '2.16.840.1.113733.1.6.9' => 'verisignPrivate',
+ // for Certificate Signing Requests
+ // see http://tools.ietf.org/html/rfc2985
+ '1.2.840.113549.1.9.2' => 'pkcs-9-at-unstructuredName', // PKCS #9 unstructured name
+ '1.2.840.113549.1.9.7' => 'pkcs-9-at-challengePassword', // Challenge password for certificate revocations
+ '1.2.840.113549.1.9.14' => 'pkcs-9-at-extensionRequest' // Certificate extension request
+ );
+ }
+
+ /**
+ * Load X.509 certificate
+ *
+ * Returns an associative array describing the X.509 cert or a false if the cert failed to load
+ *
+ * @param string $cert
+ * @param int $mode
+ * @access public
+ * @return mixed
+ */
+ function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
+ {
+ if (is_array($cert) && isset($cert['tbsCertificate'])) {
+ unset($this->currentCert);
+ unset($this->currentKeyIdentifier);
+ $this->dn = $cert['tbsCertificate']['subject'];
+ if (!isset($this->dn)) {
+ return false;
+ }
+ $this->currentCert = $cert;
+
+ $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
+ $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
+
+ unset($this->signatureSubject);
+
+ return $cert;
+ }
+
+ $asn1 = new ASN1();
+
+ if ($mode != self::FORMAT_DER) {
+ $newcert = $this->_extractBER($cert);
+ if ($mode == self::FORMAT_PEM && $cert == $newcert) {
+ return false;
+ }
+ $cert = $newcert;
+ }
+
+ if ($cert === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $asn1->loadOIDs($this->oids);
+ $decoded = $asn1->decodeBER($cert);
+
+ if (!empty($decoded)) {
+ $x509 = $asn1->asn1map($decoded[0], $this->Certificate);
+ }
+ if (!isset($x509) || $x509 === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
+
+ if ($this->_isSubArrayValid($x509, 'tbsCertificate/extensions')) {
+ $this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
+ }
+ $this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
+ $this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $asn1);
+
+ $key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'];
+ $key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key);
+
+ $this->currentCert = $x509;
+ $this->dn = $x509['tbsCertificate']['subject'];
+
+ $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
+ $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
+
+ return $x509;
+ }
+
+ /**
+ * Save X.509 certificate
+ *
+ * @param array $cert
+ * @param int $format optional
+ * @access public
+ * @return string
+ */
+ function saveX509($cert, $format = self::FORMAT_PEM)
+ {
+ if (!is_array($cert) || !isset($cert['tbsCertificate'])) {
+ return false;
+ }
+
+ switch (true) {
+ // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()"
+ case !($algorithm = $this->_subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')):
+ case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
+ break;
+ default:
+ switch ($algorithm) {
+ case 'rsaEncryption':
+ $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
+ = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
+ /* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier."
+ -- https://tools.ietf.org/html/rfc3279#section-2.3.1
+
+ given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank,
+ it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever.
+ */
+ $cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null;
+ // https://tools.ietf.org/html/rfc3279#section-2.2.1
+ $cert['signatureAlgorithm']['parameters'] = null;
+ $cert['tbsCertificate']['signature']['parameters'] = null;
+ }
+ }
+
+ $asn1 = new ASN1();
+ $asn1->loadOIDs($this->oids);
+
+ $filters = array();
+ $type_utf8_string = array('type' => ASN1::TYPE_UTF8_STRING);
+ $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string;
+ $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string;
+ $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string;
+ $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string;
+ $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string;
+ $filters['signatureAlgorithm']['parameters'] = $type_utf8_string;
+ $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
+ //$filters['policyQualifiers']['qualifier'] = $type_utf8_string;
+ $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
+ $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string;
+
+ /* in the case of policyQualifiers/qualifier, the type has to be \phpseclib\File\ASN1::TYPE_IA5_STRING.
+ \phpseclib\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
+ characters.
+ */
+ $filters['policyQualifiers']['qualifier']
+ = array('type' => ASN1::TYPE_IA5_STRING);
+
+ $asn1->loadFilters($filters);
+
+ $this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1);
+ $this->_mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence', $asn1);
+ $this->_mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence', $asn1);
+
+ $cert = $asn1->encodeDER($cert, $this->Certificate);
+
+ switch ($format) {
+ case self::FORMAT_DER:
+ return $cert;
+ // case self::FORMAT_PEM:
+ default:
+ return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(base64_encode($cert), 64) . '-----END CERTIFICATE-----';
+ }
+ }
+
+ /**
+ * Map extension values from octet string to extension-specific internal
+ * format.
+ *
+ * @param array ref $root
+ * @param string $path
+ * @param object $asn1
+ * @access private
+ */
+ function _mapInExtensions(&$root, $path, $asn1)
+ {
+ $extensions = &$this->_subArrayUnchecked($root, $path);
+
+ if ($extensions) {
+ for ($i = 0; $i < count($extensions); $i++) {
+ $id = $extensions[$i]['extnId'];
+ $value = &$extensions[$i]['extnValue'];
+ $value = base64_decode($value);
+ $decoded = $asn1->decodeBER($value);
+ /* [extnValue] contains the DER encoding of an ASN.1 value
+ corresponding to the extension type identified by extnID */
+ $map = $this->_getMapping($id);
+ if (!is_bool($map)) {
+ $mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => array($this, '_decodeIP')));
+ $value = $mapped === false ? $decoded[0] : $mapped;
+
+ if ($id == 'id-ce-certificatePolicies') {
+ for ($j = 0; $j < count($value); $j++) {
+ if (!isset($value[$j]['policyQualifiers'])) {
+ continue;
+ }
+ for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
+ $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
+ $map = $this->_getMapping($subid);
+ $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
+ if ($map !== false) {
+ $decoded = $asn1->decodeBER($subvalue);
+ $mapped = $asn1->asn1map($decoded[0], $map);
+ $subvalue = $mapped === false ? $decoded[0] : $mapped;
+ }
+ }
+ }
+ }
+ } else {
+ $value = base64_encode($value);
+ }
+ }
+ }
+ }
+
+ /**
+ * Map extension values from extension-specific internal format to
+ * octet string.
+ *
+ * @param array ref $root
+ * @param string $path
+ * @param object $asn1
+ * @access private
+ */
+ function _mapOutExtensions(&$root, $path, $asn1)
+ {
+ $extensions = &$this->_subArray($root, $path);
+
+ if (is_array($extensions)) {
+ $size = count($extensions);
+ for ($i = 0; $i < $size; $i++) {
+ if ($extensions[$i] instanceof Element) {
+ continue;
+ }
+
+ $id = $extensions[$i]['extnId'];
+ $value = &$extensions[$i]['extnValue'];
+
+ switch ($id) {
+ case 'id-ce-certificatePolicies':
+ for ($j = 0; $j < count($value); $j++) {
+ if (!isset($value[$j]['policyQualifiers'])) {
+ continue;
+ }
+ for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
+ $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
+ $map = $this->_getMapping($subid);
+ $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
+ if ($map !== false) {
+ // by default \phpseclib\File\ASN1 will try to render qualifier as a \phpseclib\File\ASN1::TYPE_IA5_STRING since it's
+ // actual type is \phpseclib\File\ASN1::TYPE_ANY
+ $subvalue = new Element($asn1->encodeDER($subvalue, $map));
+ }
+ }
+ }
+ break;
+ case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string
+ if (isset($value['authorityCertSerialNumber'])) {
+ if ($value['authorityCertSerialNumber']->toBytes() == '') {
+ $temp = chr((ASN1::CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0";
+ $value['authorityCertSerialNumber'] = new Element($temp);
+ }
+ }
+ }
+
+ /* [extnValue] contains the DER encoding of an ASN.1 value
+ corresponding to the extension type identified by extnID */
+ $map = $this->_getMapping($id);
+ if (is_bool($map)) {
+ if (!$map) {
+ user_error($id . ' is not a currently supported extension');
+ unset($extensions[$i]);
+ }
+ } else {
+ $temp = $asn1->encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
+ $value = base64_encode($temp);
+ }
+ }
+ }
+ }
+
+ /**
+ * Map attribute values from ANY type to attribute-specific internal
+ * format.
+ *
+ * @param array ref $root
+ * @param string $path
+ * @param object $asn1
+ * @access private
+ */
+ function _mapInAttributes(&$root, $path, $asn1)
+ {
+ $attributes = &$this->_subArray($root, $path);
+
+ if (is_array($attributes)) {
+ for ($i = 0; $i < count($attributes); $i++) {
+ $id = $attributes[$i]['type'];
+ /* $value contains the DER encoding of an ASN.1 value
+ corresponding to the attribute type identified by type */
+ $map = $this->_getMapping($id);
+ if (is_array($attributes[$i]['value'])) {
+ $values = &$attributes[$i]['value'];
+ for ($j = 0; $j < count($values); $j++) {
+ $value = $asn1->encodeDER($values[$j], $this->AttributeValue);
+ $decoded = $asn1->decodeBER($value);
+ if (!is_bool($map)) {
+ $mapped = $asn1->asn1map($decoded[0], $map);
+ if ($mapped !== false) {
+ $values[$j] = $mapped;
+ }
+ if ($id == 'pkcs-9-at-extensionRequest' && $this->_isSubArrayValid($values, $j)) {
+ $this->_mapInExtensions($values, $j, $asn1);
+ }
+ } elseif ($map) {
+ $values[$j] = base64_encode($value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Map attribute values from attribute-specific internal format to
+ * ANY type.
+ *
+ * @param array ref $root
+ * @param string $path
+ * @param object $asn1
+ * @access private
+ */
+ function _mapOutAttributes(&$root, $path, $asn1)
+ {
+ $attributes = &$this->_subArray($root, $path);
+
+ if (is_array($attributes)) {
+ $size = count($attributes);
+ for ($i = 0; $i < $size; $i++) {
+ /* [value] contains the DER encoding of an ASN.1 value
+ corresponding to the attribute type identified by type */
+ $id = $attributes[$i]['type'];
+ $map = $this->_getMapping($id);
+ if ($map === false) {
+ user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
+ unset($attributes[$i]);
+ } elseif (is_array($attributes[$i]['value'])) {
+ $values = &$attributes[$i]['value'];
+ for ($j = 0; $j < count($values); $j++) {
+ switch ($id) {
+ case 'pkcs-9-at-extensionRequest':
+ $this->_mapOutExtensions($values, $j, $asn1);
+ break;
+ }
+
+ if (!is_bool($map)) {
+ $temp = $asn1->encodeDER($values[$j], $map);
+ $decoded = $asn1->decodeBER($temp);
+ $values[$j] = $asn1->asn1map($decoded[0], $this->AttributeValue);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Map DN values from ANY type to DN-specific internal
+ * format.
+ *
+ * @param array ref $root
+ * @param string $path
+ * @param object $asn1
+ * @access private
+ */
+ function _mapInDNs(&$root, $path, $asn1)
+ {
+ $dns = &$this->_subArray($root, $path);
+
+ if (is_array($dns)) {
+ for ($i = 0; $i < count($dns); $i++) {
+ for ($j = 0; $j < count($dns[$i]); $j++) {
+ $type = $dns[$i][$j]['type'];
+ $value = &$dns[$i][$j]['value'];
+ if (is_object($value) && $value instanceof Element) {
+ $map = $this->_getMapping($type);
+ if (!is_bool($map)) {
+ $decoded = $asn1->decodeBER($value);
+ $value = $asn1->asn1map($decoded[0], $map);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Map DN values from DN-specific internal format to
+ * ANY type.
+ *
+ * @param array ref $root
+ * @param string $path
+ * @param object $asn1
+ * @access private
+ */
+ function _mapOutDNs(&$root, $path, $asn1)
+ {
+ $dns = &$this->_subArray($root, $path);
+
+ if (is_array($dns)) {
+ $size = count($dns);
+ for ($i = 0; $i < $size; $i++) {
+ for ($j = 0; $j < count($dns[$i]); $j++) {
+ $type = $dns[$i][$j]['type'];
+ $value = &$dns[$i][$j]['value'];
+ if (is_object($value) && $value instanceof Element) {
+ continue;
+ }
+
+ $map = $this->_getMapping($type);
+ if (!is_bool($map)) {
+ $value = new Element($asn1->encodeDER($value, $map));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Associate an extension ID to an extension mapping
+ *
+ * @param string $extnId
+ * @access private
+ * @return mixed
+ */
+ function _getMapping($extnId)
+ {
+ if (!is_string($extnId)) { // eg. if it's a \phpseclib\File\ASN1\Element object
+ return true;
+ }
+
+ switch ($extnId) {
+ case 'id-ce-keyUsage':
+ return $this->KeyUsage;
+ case 'id-ce-basicConstraints':
+ return $this->BasicConstraints;
+ case 'id-ce-subjectKeyIdentifier':
+ return $this->KeyIdentifier;
+ case 'id-ce-cRLDistributionPoints':
+ return $this->CRLDistributionPoints;
+ case 'id-ce-authorityKeyIdentifier':
+ return $this->AuthorityKeyIdentifier;
+ case 'id-ce-certificatePolicies':
+ return $this->CertificatePolicies;
+ case 'id-ce-extKeyUsage':
+ return $this->ExtKeyUsageSyntax;
+ case 'id-pe-authorityInfoAccess':
+ return $this->AuthorityInfoAccessSyntax;
+ case 'id-ce-subjectAltName':
+ return $this->SubjectAltName;
+ case 'id-ce-subjectDirectoryAttributes':
+ return $this->SubjectDirectoryAttributes;
+ case 'id-ce-privateKeyUsagePeriod':
+ return $this->PrivateKeyUsagePeriod;
+ case 'id-ce-issuerAltName':
+ return $this->IssuerAltName;
+ case 'id-ce-policyMappings':
+ return $this->PolicyMappings;
+ case 'id-ce-nameConstraints':
+ return $this->NameConstraints;
+
+ case 'netscape-cert-type':
+ return $this->netscape_cert_type;
+ case 'netscape-comment':
+ return $this->netscape_comment;
+ case 'netscape-ca-policy-url':
+ return $this->netscape_ca_policy_url;
+
+ // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets
+ // back around to asn1map() and we don't want it decoded again.
+ //case 'id-qt-cps':
+ // return $this->CPSuri;
+ case 'id-qt-unotice':
+ return $this->UserNotice;
+
+ // the following OIDs are unsupported but we don't want them to give notices when calling saveX509().
+ case 'id-pe-logotype': // http://www.ietf.org/rfc/rfc3709.txt
+ case 'entrustVersInfo':
+ // http://support.microsoft.com/kb/287547
+ case '1.3.6.1.4.1.311.20.2': // szOID_ENROLL_CERTTYPE_EXTENSION
+ case '1.3.6.1.4.1.311.21.1': // szOID_CERTSRV_CA_VERSION
+ // "SET Secure Electronic Transaction Specification"
+ // http://www.maithean.com/docs/set_bk3.pdf
+ case '2.23.42.7.0': // id-set-hashedRootKey
+ // "Certificate Transparency"
+ // https://tools.ietf.org/html/rfc6962
+ case '1.3.6.1.4.1.11129.2.4.2':
+ // "Qualified Certificate statements"
+ // https://tools.ietf.org/html/rfc3739#section-3.2.6
+ case '1.3.6.1.5.5.7.1.3':
+ return true;
+
+ // CSR attributes
+ case 'pkcs-9-at-unstructuredName':
+ return $this->PKCS9String;
+ case 'pkcs-9-at-challengePassword':
+ return $this->DirectoryString;
+ case 'pkcs-9-at-extensionRequest':
+ return $this->Extensions;
+
+ // CRL extensions.
+ case 'id-ce-cRLNumber':
+ return $this->CRLNumber;
+ case 'id-ce-deltaCRLIndicator':
+ return $this->CRLNumber;
+ case 'id-ce-issuingDistributionPoint':
+ return $this->IssuingDistributionPoint;
+ case 'id-ce-freshestCRL':
+ return $this->CRLDistributionPoints;
+ case 'id-ce-cRLReasons':
+ return $this->CRLReason;
+ case 'id-ce-invalidityDate':
+ return $this->InvalidityDate;
+ case 'id-ce-certificateIssuer':
+ return $this->CertificateIssuer;
+ case 'id-ce-holdInstructionCode':
+ return $this->HoldInstructionCode;
+ case 'id-at-postalAddress':
+ return $this->PostalAddress;
+ }
+
+ return false;
+ }
+
+ /**
+ * Load an X.509 certificate as a certificate authority
+ *
+ * @param string $cert
+ * @access public
+ * @return bool
+ */
+ function loadCA($cert)
+ {
+ $olddn = $this->dn;
+ $oldcert = $this->currentCert;
+ $oldsigsubj = $this->signatureSubject;
+ $oldkeyid = $this->currentKeyIdentifier;
+
+ $cert = $this->loadX509($cert);
+ if (!$cert) {
+ $this->dn = $olddn;
+ $this->currentCert = $oldcert;
+ $this->signatureSubject = $oldsigsubj;
+ $this->currentKeyIdentifier = $oldkeyid;
+
+ return false;
+ }
+
+ /* From RFC5280 "PKIX Certificate and CRL Profile":
+
+ If the keyUsage extension is present, then the subject public key
+ MUST NOT be used to verify signatures on certificates or CRLs unless
+ the corresponding keyCertSign or cRLSign bit is set. */
+ //$keyUsage = $this->getExtension('id-ce-keyUsage');
+ //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) {
+ // return false;
+ //}
+
+ /* From RFC5280 "PKIX Certificate and CRL Profile":
+
+ The cA boolean indicates whether the certified public key may be used
+ to verify certificate signatures. If the cA boolean is not asserted,
+ then the keyCertSign bit in the key usage extension MUST NOT be
+ asserted. If the basic constraints extension is not present in a
+ version 3 certificate, or the extension is present but the cA boolean
+ is not asserted, then the certified public key MUST NOT be used to
+ verify certificate signatures. */
+ //$basicConstraints = $this->getExtension('id-ce-basicConstraints');
+ //if (!$basicConstraints || !$basicConstraints['cA']) {
+ // return false;
+ //}
+
+ $this->CAs[] = $cert;
+
+ $this->dn = $olddn;
+ $this->currentCert = $oldcert;
+ $this->signatureSubject = $oldsigsubj;
+
+ return true;
+ }
+
+ /**
+ * Validate an X.509 certificate against a URL
+ *
+ * From RFC2818 "HTTP over TLS":
+ *
+ * Matching is performed using the matching rules specified by
+ * [RFC2459]. If more than one identity of a given type is present in
+ * the certificate (e.g., more than one dNSName name, a match in any one
+ * of the set is considered acceptable.) Names may contain the wildcard
+ * character * which is considered to match any single domain name
+ * component or component fragment. E.g., *.a.com matches foo.a.com but
+ * not bar.foo.a.com. f*.com matches foo.com but not bar.com.
+ *
+ * @param string $url
+ * @access public
+ * @return bool
+ */
+ function validateURL($url)
+ {
+ if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
+ return false;
+ }
+
+ $components = parse_url($url);
+ if (!isset($components['host'])) {
+ return false;
+ }
+
+ if ($names = $this->getExtension('id-ce-subjectAltName')) {
+ foreach ($names as $name) {
+ foreach ($name as $key => $value) {
+ $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
+ switch ($key) {
+ case 'dNSName':
+ /* From RFC2818 "HTTP over TLS":
+
+ If a subjectAltName extension of type dNSName is present, that MUST
+ be used as the identity. Otherwise, the (most specific) Common Name
+ field in the Subject field of the certificate MUST be used. Although
+ the use of the Common Name is existing practice, it is deprecated and
+ Certification Authorities are encouraged to use the dNSName instead. */
+ if (preg_match('#^' . $value . '$#', $components['host'])) {
+ return true;
+ }
+ break;
+ case 'iPAddress':
+ /* From RFC2818 "HTTP over TLS":
+
+ In some cases, the URI is specified as an IP address rather than a
+ hostname. In this case, the iPAddress subjectAltName must be present
+ in the certificate and must exactly match the IP in the URI. */
+ if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ if ($value = $this->getDNProp('id-at-commonName')) {
+ $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value[0]);
+ return preg_match('#^' . $value . '$#', $components['host']);
+ }
+
+ return false;
+ }
+
+ /**
+ * Validate a date
+ *
+ * If $date isn't defined it is assumed to be the current date.
+ *
+ * @param \DateTime|string $date optional
+ * @access public
+ */
+ function validateDate($date = null)
+ {
+ if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
+ return false;
+ }
+
+ if (!isset($date)) {
+ $date = new DateTime(null, new DateTimeZone(@date_default_timezone_get()));
+ }
+
+ $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
+ $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime'];
+
+ $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
+ $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
+
+ if (is_string($date)) {
+ $date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
+ }
+
+ $notBefore = new DateTime($notBefore, new DateTimeZone(@date_default_timezone_get()));
+ $notAfter = new DateTime($notAfter, new DateTimeZone(@date_default_timezone_get()));
+
+ switch (true) {
+ case $date < $notBefore:
+ case $date > $notAfter:
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Fetches a URL
+ *
+ * @param string $url
+ * @access private
+ * @return bool|string
+ */
+ static function _fetchURL($url)
+ {
+ if (self::$disable_url_fetch) {
+ return false;
+ }
+
+ $parts = parse_url($url);
+ $data = '';
+ switch ($parts['scheme']) {
+ case 'http':
+ $fsock = @fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80);
+ if (!$fsock) {
+ return false;
+ }
+ fputs($fsock, "GET $parts[path] HTTP/1.0\r\n");
+ fputs($fsock, "Host: $parts[host]\r\n\r\n");
+ $line = fgets($fsock, 1024);
+ if (strlen($line) < 3) {
+ return false;
+ }
+ preg_match('#HTTP/1.\d (\d{3})#', $line, $temp);
+ if ($temp[1] != '200') {
+ return false;
+ }
+
+ // skip the rest of the headers in the http response
+ while (!feof($fsock) && fgets($fsock, 1024) != "\r\n") {
+ }
+
+ while (!feof($fsock)) {
+ $data.= fread($fsock, 1024);
+ }
+
+ break;
+ //case 'ftp':
+ //case 'ldap':
+ //default:
+ }
+
+ return $data;
+ }
+
+ /**
+ * Validates an intermediate cert as identified via authority info access extension
+ *
+ * See https://tools.ietf.org/html/rfc4325 for more info
+ *
+ * @param bool $caonly
+ * @param int $count
+ * @access private
+ * @return bool
+ */
+ function _testForIntermediate($caonly, $count)
+ {
+ $opts = $this->getExtension('id-pe-authorityInfoAccess');
+ if (!is_array($opts)) {
+ return false;
+ }
+ foreach ($opts as $opt) {
+ if ($opt['accessMethod'] == 'id-ad-caIssuers') {
+ // accessLocation is a GeneralName. GeneralName fields support stuff like email addresses, IP addresses, LDAP,
+ // etc, but we're only supporting URI's. URI's and LDAP are the only thing https://tools.ietf.org/html/rfc4325
+ // discusses
+ if (isset($opt['accessLocation']['uniformResourceIdentifier'])) {
+ $url = $opt['accessLocation']['uniformResourceIdentifier'];
+ break;
+ }
+ }
+ }
+
+ if (!isset($url)) {
+ return false;
+ }
+
+ $cert = static::_fetchURL($url);
+ if (!is_string($cert)) {
+ return false;
+ }
+
+ $parent = new static();
+ $parent->CAs = $this->CAs;
+ /*
+ "Conforming applications that support HTTP or FTP for accessing
+ certificates MUST be able to accept .cer files and SHOULD be able
+ to accept .p7c files." -- https://tools.ietf.org/html/rfc4325
+
+ A .p7c file is 'a "certs-only" CMS message as specified in RFC 2797"
+
+ These are currently unsupported
+ */
+ if (!is_array($parent->loadX509($cert))) {
+ return false;
+ }
+
+ if (!$parent->_validateSignatureCountable($caonly, ++$count)) {
+ return false;
+ }
+
+ $this->CAs[] = $parent->currentCert;
+ //$this->loadCA($cert);
+
+ return true;
+ }
+
+ /**
+ * Validate a signature
+ *
+ * Works on X.509 certs, CSR's and CRL's.
+ * Returns true if the signature is verified, false if it is not correct or null on error
+ *
+ * By default returns false for self-signed certs. Call validateSignature(false) to make this support
+ * self-signed.
+ *
+ * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
+ *
+ * @param bool $caonly optional
+ * @access public
+ * @return mixed
+ */
+ function validateSignature($caonly = true)
+ {
+ return $this->_validateSignatureCountable($caonly, 0);
+ }
+
+ /**
+ * Validate a signature
+ *
+ * Performs said validation whilst keeping track of how many times validation method is called
+ *
+ * @param bool $caonly
+ * @param int $count
+ * @access private
+ * @return mixed
+ */
+ function _validateSignatureCountable($caonly, $count)
+ {
+ if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
+ return null;
+ }
+
+ if ($count == self::$recur_limit) {
+ return false;
+ }
+
+ /* TODO:
+ "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")."
+ -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
+
+ implement pathLenConstraint in the id-ce-basicConstraints extension */
+
+ switch (true) {
+ case isset($this->currentCert['tbsCertificate']):
+ // self-signed cert
+ switch (true) {
+ case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
+ case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING):
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
+ switch (true) {
+ case !is_array($authorityKey):
+ case !$subjectKeyID:
+ case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
+ $signingCert = $this->currentCert; // working cert
+ }
+ }
+
+ if (!empty($this->CAs)) {
+ for ($i = 0; $i < count($this->CAs); $i++) {
+ // even if the cert is a self-signed one we still want to see if it's a CA;
+ // if not, we'll conditionally return an error
+ $ca = $this->CAs[$i];
+ switch (true) {
+ case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
+ case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
+ switch (true) {
+ case !is_array($authorityKey):
+ case !$subjectKeyID:
+ case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
+ if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
+ break 2; // serial mismatch - check other ca
+ }
+ $signingCert = $ca; // working cert
+ break 3;
+ }
+ }
+ }
+ if (count($this->CAs) == $i && $caonly) {
+ return $this->_testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
+ }
+ } elseif (!isset($signingCert) || $caonly) {
+ return $this->_testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
+ }
+ return $this->_validateSignature(
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
+ $this->currentCert['signatureAlgorithm']['algorithm'],
+ substr(base64_decode($this->currentCert['signature']), 1),
+ $this->signatureSubject
+ );
+ case isset($this->currentCert['certificationRequestInfo']):
+ return $this->_validateSignature(
+ $this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'],
+ $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'],
+ $this->currentCert['signatureAlgorithm']['algorithm'],
+ substr(base64_decode($this->currentCert['signature']), 1),
+ $this->signatureSubject
+ );
+ case isset($this->currentCert['publicKeyAndChallenge']):
+ return $this->_validateSignature(
+ $this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'],
+ $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'],
+ $this->currentCert['signatureAlgorithm']['algorithm'],
+ substr(base64_decode($this->currentCert['signature']), 1),
+ $this->signatureSubject
+ );
+ case isset($this->currentCert['tbsCertList']):
+ if (!empty($this->CAs)) {
+ for ($i = 0; $i < count($this->CAs); $i++) {
+ $ca = $this->CAs[$i];
+ switch (true) {
+ case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
+ case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
+ switch (true) {
+ case !is_array($authorityKey):
+ case !$subjectKeyID:
+ case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
+ if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
+ break 2; // serial mismatch - check other ca
+ }
+ $signingCert = $ca; // working cert
+ break 3;
+ }
+ }
+ }
+ }
+ if (!isset($signingCert)) {
+ return false;
+ }
+ return $this->_validateSignature(
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
+ $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
+ $this->currentCert['signatureAlgorithm']['algorithm'],
+ substr(base64_decode($this->currentCert['signature']), 1),
+ $this->signatureSubject
+ );
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Validates a signature
+ *
+ * Returns true if the signature is verified, false if it is not correct or null on error
+ *
+ * @param string $publicKeyAlgorithm
+ * @param string $publicKey
+ * @param string $signatureAlgorithm
+ * @param string $signature
+ * @param string $signatureSubject
+ * @access private
+ * @return int
+ */
+ function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
+ {
+ switch ($publicKeyAlgorithm) {
+ case 'rsaEncryption':
+ $rsa = new RSA();
+ $rsa->loadKey($publicKey);
+
+ switch ($signatureAlgorithm) {
+ case 'md2WithRSAEncryption':
+ case 'md5WithRSAEncryption':
+ case 'sha1WithRSAEncryption':
+ case 'sha224WithRSAEncryption':
+ case 'sha256WithRSAEncryption':
+ case 'sha384WithRSAEncryption':
+ case 'sha512WithRSAEncryption':
+ $rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
+ $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
+ if (!@$rsa->verify($signatureSubject, $signature)) {
+ return false;
+ }
+ break;
+ default:
+ return null;
+ }
+ break;
+ default:
+ return null;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the recursion limit
+ *
+ * When validating a signature it may be necessary to download intermediate certs from URI's.
+ * An intermediate cert that linked to itself would result in an infinite loop so to prevent
+ * that we set a recursion limit. A negative number means that there is no recursion limit.
+ *
+ * @param int $count
+ * @access public
+ */
+ static function setRecurLimit($count)
+ {
+ self::$recur_limit = $count;
+ }
+
+ /**
+ * Prevents URIs from being automatically retrieved
+ *
+ * @access public
+ */
+ static function disableURLFetch()
+ {
+ self::$disable_url_fetch = true;
+ }
+
+ /**
+ * Allows URIs to be automatically retrieved
+ *
+ * @access public
+ */
+ static function enableURLFetch()
+ {
+ self::$disable_url_fetch = false;
+ }
+
+ /**
+ * Reformat public keys
+ *
+ * Reformats a public key to a format supported by phpseclib (if applicable)
+ *
+ * @param string $algorithm
+ * @param string $key
+ * @access private
+ * @return string
+ */
+ function _reformatKey($algorithm, $key)
+ {
+ switch ($algorithm) {
+ case 'rsaEncryption':
+ return
+ "-----BEGIN RSA PUBLIC KEY-----\r\n" .
+ // subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits
+ // in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox
+ // uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
+ chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) .
+ '-----END RSA PUBLIC KEY-----';
+ default:
+ return $key;
+ }
+ }
+
+ /**
+ * Decodes an IP address
+ *
+ * Takes in a base64 encoded "blob" and returns a human readable IP address
+ *
+ * @param string $ip
+ * @access private
+ * @return string
+ */
+ function _decodeIP($ip)
+ {
+ return inet_ntop(base64_decode($ip));
+ }
+
+ /**
+ * Encodes an IP address
+ *
+ * Takes a human readable IP address into a base64-encoded "blob"
+ *
+ * @param string $ip
+ * @access private
+ * @return string
+ */
+ function _encodeIP($ip)
+ {
+ return base64_encode(inet_pton($ip));
+ }
+
+ /**
+ * "Normalizes" a Distinguished Name property
+ *
+ * @param string $propName
+ * @access private
+ * @return mixed
+ */
+ function _translateDNProp($propName)
+ {
+ switch (strtolower($propName)) {
+ case 'id-at-countryname':
+ case 'countryname':
+ case 'c':
+ return 'id-at-countryName';
+ case 'id-at-organizationname':
+ case 'organizationname':
+ case 'o':
+ return 'id-at-organizationName';
+ case 'id-at-dnqualifier':
+ case 'dnqualifier':
+ return 'id-at-dnQualifier';
+ case 'id-at-commonname':
+ case 'commonname':
+ case 'cn':
+ return 'id-at-commonName';
+ case 'id-at-stateorprovincename':
+ case 'stateorprovincename':
+ case 'state':
+ case 'province':
+ case 'provincename':
+ case 'st':
+ return 'id-at-stateOrProvinceName';
+ case 'id-at-localityname':
+ case 'localityname':
+ case 'l':
+ return 'id-at-localityName';
+ case 'id-emailaddress':
+ case 'emailaddress':
+ return 'pkcs-9-at-emailAddress';
+ case 'id-at-serialnumber':
+ case 'serialnumber':
+ return 'id-at-serialNumber';
+ case 'id-at-postalcode':
+ case 'postalcode':
+ return 'id-at-postalCode';
+ case 'id-at-streetaddress':
+ case 'streetaddress':
+ return 'id-at-streetAddress';
+ case 'id-at-name':
+ case 'name':
+ return 'id-at-name';
+ case 'id-at-givenname':
+ case 'givenname':
+ return 'id-at-givenName';
+ case 'id-at-surname':
+ case 'surname':
+ case 'sn':
+ return 'id-at-surname';
+ case 'id-at-initials':
+ case 'initials':
+ return 'id-at-initials';
+ case 'id-at-generationqualifier':
+ case 'generationqualifier':
+ return 'id-at-generationQualifier';
+ case 'id-at-organizationalunitname':
+ case 'organizationalunitname':
+ case 'ou':
+ return 'id-at-organizationalUnitName';
+ case 'id-at-pseudonym':
+ case 'pseudonym':
+ return 'id-at-pseudonym';
+ case 'id-at-title':
+ case 'title':
+ return 'id-at-title';
+ case 'id-at-description':
+ case 'description':
+ return 'id-at-description';
+ case 'id-at-role':
+ case 'role':
+ return 'id-at-role';
+ case 'id-at-uniqueidentifier':
+ case 'uniqueidentifier':
+ case 'x500uniqueidentifier':
+ return 'id-at-uniqueIdentifier';
+ case 'postaladdress':
+ case 'id-at-postaladdress':
+ return 'id-at-postalAddress';
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Set a Distinguished Name property
+ *
+ * @param string $propName
+ * @param mixed $propValue
+ * @param string $type optional
+ * @access public
+ * @return bool
+ */
+ function setDNProp($propName, $propValue, $type = 'utf8String')
+ {
+ if (empty($this->dn)) {
+ $this->dn = array('rdnSequence' => array());
+ }
+
+ if (($propName = $this->_translateDNProp($propName)) === false) {
+ return false;
+ }
+
+ foreach ((array) $propValue as $v) {
+ if (!is_array($v) && isset($type)) {
+ $v = array($type => $v);
+ }
+ $this->dn['rdnSequence'][] = array(
+ array(
+ 'type' => $propName,
+ 'value'=> $v
+ )
+ );
+ }
+
+ return true;
+ }
+
+ /**
+ * Remove Distinguished Name properties
+ *
+ * @param string $propName
+ * @access public
+ */
+ function removeDNProp($propName)
+ {
+ if (empty($this->dn)) {
+ return;
+ }
+
+ if (($propName = $this->_translateDNProp($propName)) === false) {
+ return;
+ }
+
+ $dn = &$this->dn['rdnSequence'];
+ $size = count($dn);
+ for ($i = 0; $i < $size; $i++) {
+ if ($dn[$i][0]['type'] == $propName) {
+ unset($dn[$i]);
+ }
+ }
+
+ $dn = array_values($dn);
+ // fix for https://bugs.php.net/75433 affecting PHP 7.2
+ if (!isset($dn[0])) {
+ $dn = array_splice($dn, 0, 0);
+ }
+ }
+
+ /**
+ * Get Distinguished Name properties
+ *
+ * @param string $propName
+ * @param array $dn optional
+ * @param bool $withType optional
+ * @return mixed
+ * @access public
+ */
+ function getDNProp($propName, $dn = null, $withType = false)
+ {
+ if (!isset($dn)) {
+ $dn = $this->dn;
+ }
+
+ if (empty($dn)) {
+ return false;
+ }
+
+ if (($propName = $this->_translateDNProp($propName)) === false) {
+ return false;
+ }
+
+ $asn1 = new ASN1();
+ $asn1->loadOIDs($this->oids);
+ $filters = array();
+ $filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
+ $asn1->loadFilters($filters);
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
+ $dn = $dn['rdnSequence'];
+ $result = array();
+ for ($i = 0; $i < count($dn); $i++) {
+ if ($dn[$i][0]['type'] == $propName) {
+ $v = $dn[$i][0]['value'];
+ if (!$withType) {
+ if (is_array($v)) {
+ foreach ($v as $type => $s) {
+ $type = array_search($type, $asn1->ANYmap, true);
+ if ($type !== false && isset($asn1->stringTypeSize[$type])) {
+ $s = $asn1->convert($s, $type);
+ if ($s !== false) {
+ $v = $s;
+ break;
+ }
+ }
+ }
+ if (is_array($v)) {
+ $v = array_pop($v); // Always strip data type.
+ }
+ } elseif (is_object($v) && $v instanceof Element) {
+ $map = $this->_getMapping($propName);
+ if (!is_bool($map)) {
+ $decoded = $asn1->decodeBER($v);
+ $v = $asn1->asn1map($decoded[0], $map);
+ }
+ }
+ }
+ $result[] = $v;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Set a Distinguished Name
+ *
+ * @param mixed $dn
+ * @param bool $merge optional
+ * @param string $type optional
+ * @access public
+ * @return bool
+ */
+ function setDN($dn, $merge = false, $type = 'utf8String')
+ {
+ if (!$merge) {
+ $this->dn = null;
+ }
+
+ if (is_array($dn)) {
+ if (isset($dn['rdnSequence'])) {
+ $this->dn = $dn; // No merge here.
+ return true;
+ }
+
+ // handles stuff generated by openssl_x509_parse()
+ foreach ($dn as $prop => $value) {
+ if (!$this->setDNProp($prop, $value, $type)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // handles everything else
+ $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
+ for ($i = 1; $i < count($results); $i+=2) {
+ $prop = trim($results[$i], ', =/');
+ $value = $results[$i + 1];
+ if (!$this->setDNProp($prop, $value, $type)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the Distinguished Name for a certificates subject
+ *
+ * @param mixed $format optional
+ * @param array $dn optional
+ * @access public
+ * @return bool
+ */
+ function getDN($format = self::DN_ARRAY, $dn = null)
+ {
+ if (!isset($dn)) {
+ $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
+ }
+
+ switch ((int) $format) {
+ case self::DN_ARRAY:
+ return $dn;
+ case self::DN_ASN1:
+ $asn1 = new ASN1();
+ $asn1->loadOIDs($this->oids);
+ $filters = array();
+ $filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
+ $asn1->loadFilters($filters);
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
+ return $asn1->encodeDER($dn, $this->Name);
+ case self::DN_CANON:
+ // No SEQUENCE around RDNs and all string values normalized as
+ // trimmed lowercase UTF-8 with all spacing as one blank.
+ // constructed RDNs will not be canonicalized
+ $asn1 = new ASN1();
+ $asn1->loadOIDs($this->oids);
+ $filters = array();
+ $filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
+ $asn1->loadFilters($filters);
+ $result = '';
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
+ foreach ($dn['rdnSequence'] as $rdn) {
+ foreach ($rdn as $i => $attr) {
+ $attr = &$rdn[$i];
+ if (is_array($attr['value'])) {
+ foreach ($attr['value'] as $type => $v) {
+ $type = array_search($type, $asn1->ANYmap, true);
+ if ($type !== false && isset($asn1->stringTypeSize[$type])) {
+ $v = $asn1->convert($v, $type);
+ if ($v !== false) {
+ $v = preg_replace('/\s+/', ' ', $v);
+ $attr['value'] = strtolower(trim($v));
+ break;
+ }
+ }
+ }
+ }
+ }
+ $result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName);
+ }
+ return $result;
+ case self::DN_HASH:
+ $dn = $this->getDN(self::DN_CANON, $dn);
+ $hash = new Hash('sha1');
+ $hash = $hash->hash($dn);
+ extract(unpack('Vhash', $hash));
+ return strtolower(bin2hex(pack('N', $hash)));
+ }
+
+ // Default is to return a string.
+ $start = true;
+ $output = '';
+
+ $result = array();
+ $asn1 = new ASN1();
+ $asn1->loadOIDs($this->oids);
+ $filters = array();
+ $filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
+ $asn1->loadFilters($filters);
+ $this->_mapOutDNs($dn, 'rdnSequence', $asn1);
+
+ foreach ($dn['rdnSequence'] as $field) {
+ $prop = $field[0]['type'];
+ $value = $field[0]['value'];
+
+ $delim = ', ';
+ switch ($prop) {
+ case 'id-at-countryName':
+ $desc = 'C';
+ break;
+ case 'id-at-stateOrProvinceName':
+ $desc = 'ST';
+ break;
+ case 'id-at-organizationName':
+ $desc = 'O';
+ break;
+ case 'id-at-organizationalUnitName':
+ $desc = 'OU';
+ break;
+ case 'id-at-commonName':
+ $desc = 'CN';
+ break;
+ case 'id-at-localityName':
+ $desc = 'L';
+ break;
+ case 'id-at-surname':
+ $desc = 'SN';
+ break;
+ case 'id-at-uniqueIdentifier':
+ $delim = '/';
+ $desc = 'x500UniqueIdentifier';
+ break;
+ case 'id-at-postalAddress':
+ $delim = '/';
+ $desc = 'postalAddress';
+ break;
+ default:
+ $delim = '/';
+ $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
+ }
+
+ if (!$start) {
+ $output.= $delim;
+ }
+ if (is_array($value)) {
+ foreach ($value as $type => $v) {
+ $type = array_search($type, $asn1->ANYmap, true);
+ if ($type !== false && isset($asn1->stringTypeSize[$type])) {
+ $v = $asn1->convert($v, $type);
+ if ($v !== false) {
+ $value = $v;
+ break;
+ }
+ }
+ }
+ if (is_array($value)) {
+ $value = array_pop($value); // Always strip data type.
+ }
+ } elseif (is_object($value) && $value instanceof Element) {
+ $callback = function ($x) {
+ return "\x" . bin2hex($x[0]);
+ };
+ $value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
+ }
+ $output.= $desc . '=' . $value;
+ $result[$desc] = isset($result[$desc]) ?
+ array_merge((array) $result[$desc], array($value)) :
+ $value;
+ $start = false;
+ }
+
+ return $format == self::DN_OPENSSL ? $result : $output;
+ }
+
+ /**
+ * Get the Distinguished Name for a certificate/crl issuer
+ *
+ * @param int $format optional
+ * @access public
+ * @return mixed
+ */
+ function getIssuerDN($format = self::DN_ARRAY)
+ {
+ switch (true) {
+ case !isset($this->currentCert) || !is_array($this->currentCert):
+ break;
+ case isset($this->currentCert['tbsCertificate']):
+ return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']);
+ case isset($this->currentCert['tbsCertList']):
+ return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']);
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the Distinguished Name for a certificate/csr subject
+ * Alias of getDN()
+ *
+ * @param int $format optional
+ * @access public
+ * @return mixed
+ */
+ function getSubjectDN($format = self::DN_ARRAY)
+ {
+ switch (true) {
+ case !empty($this->dn):
+ return $this->getDN($format);
+ case !isset($this->currentCert) || !is_array($this->currentCert):
+ break;
+ case isset($this->currentCert['tbsCertificate']):
+ return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']);
+ case isset($this->currentCert['certificationRequestInfo']):
+ return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']);
+ }
+
+ return false;
+ }
+
+ /**
+ * Get an individual Distinguished Name property for a certificate/crl issuer
+ *
+ * @param string $propName
+ * @param bool $withType optional
+ * @access public
+ * @return mixed
+ */
+ function getIssuerDNProp($propName, $withType = false)
+ {
+ switch (true) {
+ case !isset($this->currentCert) || !is_array($this->currentCert):
+ break;
+ case isset($this->currentCert['tbsCertificate']):
+ return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
+ case isset($this->currentCert['tbsCertList']):
+ return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType);
+ }
+
+ return false;
+ }
+
+ /**
+ * Get an individual Distinguished Name property for a certificate/csr subject
+ *
+ * @param string $propName
+ * @param bool $withType optional
+ * @access public
+ * @return mixed
+ */
+ function getSubjectDNProp($propName, $withType = false)
+ {
+ switch (true) {
+ case !empty($this->dn):
+ return $this->getDNProp($propName, null, $withType);
+ case !isset($this->currentCert) || !is_array($this->currentCert):
+ break;
+ case isset($this->currentCert['tbsCertificate']):
+ return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType);
+ case isset($this->currentCert['certificationRequestInfo']):
+ return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType);
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the certificate chain for the current cert
+ *
+ * @access public
+ * @return mixed
+ */
+ function getChain()
+ {
+ $chain = array($this->currentCert);
+
+ if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
+ return false;
+ }
+ if (empty($this->CAs)) {
+ return $chain;
+ }
+ while (true) {
+ $currentCert = $chain[count($chain) - 1];
+ for ($i = 0; $i < count($this->CAs); $i++) {
+ $ca = $this->CAs[$i];
+ if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) {
+ $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert);
+ $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
+ switch (true) {
+ case !is_array($authorityKey):
+ case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
+ if ($currentCert === $ca) {
+ break 3;
+ }
+ $chain[] = $ca;
+ break 2;
+ }
+ }
+ }
+ if ($i == count($this->CAs)) {
+ break;
+ }
+ }
+ foreach ($chain as $key => $value) {
+ $chain[$key] = new X509();
+ $chain[$key]->loadX509($value);
+ }
+ return $chain;
+ }
+
+ /**
+ * Set public key
+ *
+ * Key needs to be a \phpseclib\Crypt\RSA object
+ *
+ * @param object $key
+ * @access public
+ * @return bool
+ */
+ function setPublicKey($key)
+ {
+ $key->setPublicKey();
+ $this->publicKey = $key;
+ }
+
+ /**
+ * Set private key
+ *
+ * Key needs to be a \phpseclib\Crypt\RSA object
+ *
+ * @param object $key
+ * @access public
+ */
+ function setPrivateKey($key)
+ {
+ $this->privateKey = $key;
+ }
+
+ /**
+ * Set challenge
+ *
+ * Used for SPKAC CSR's
+ *
+ * @param string $challenge
+ * @access public
+ */
+ function setChallenge($challenge)
+ {
+ $this->challenge = $challenge;
+ }
+
+ /**
+ * Gets the public key
+ *
+ * Returns a \phpseclib\Crypt\RSA object or a false.
+ *
+ * @access public
+ * @return mixed
+ */
+ function getPublicKey()
+ {
+ if (isset($this->publicKey)) {
+ return $this->publicKey;
+ }
+
+ if (isset($this->currentCert) && is_array($this->currentCert)) {
+ foreach (array('tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo') as $path) {
+ $keyinfo = $this->_subArray($this->currentCert, $path);
+ if (!empty($keyinfo)) {
+ break;
+ }
+ }
+ }
+ if (empty($keyinfo)) {
+ return false;
+ }
+
+ $key = $keyinfo['subjectPublicKey'];
+
+ switch ($keyinfo['algorithm']['algorithm']) {
+ case 'rsaEncryption':
+ $publicKey = new RSA();
+ $publicKey->loadKey($key);
+ $publicKey->setPublicKey();
+ break;
+ default:
+ return false;
+ }
+
+ return $publicKey;
+ }
+
+ /**
+ * Load a Certificate Signing Request
+ *
+ * @param string $csr
+ * @access public
+ * @return mixed
+ */
+ function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
+ {
+ if (is_array($csr) && isset($csr['certificationRequestInfo'])) {
+ unset($this->currentCert);
+ unset($this->currentKeyIdentifier);
+ unset($this->signatureSubject);
+ $this->dn = $csr['certificationRequestInfo']['subject'];
+ if (!isset($this->dn)) {
+ return false;
+ }
+
+ $this->currentCert = $csr;
+ return $csr;
+ }
+
+ // see http://tools.ietf.org/html/rfc2986
+
+ $asn1 = new ASN1();
+
+ if ($mode != self::FORMAT_DER) {
+ $newcsr = $this->_extractBER($csr);
+ if ($mode == self::FORMAT_PEM && $csr == $newcsr) {
+ return false;
+ }
+ $csr = $newcsr;
+ }
+ $orig = $csr;
+
+ if ($csr === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $asn1->loadOIDs($this->oids);
+ $decoded = $asn1->decodeBER($csr);
+
+ if (empty($decoded)) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $csr = $asn1->asn1map($decoded[0], $this->CertificationRequest);
+ if (!isset($csr) || $csr === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
+ $this->_mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
+
+ $this->dn = $csr['certificationRequestInfo']['subject'];
+
+ $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
+
+ $algorithm = &$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'];
+ $key = &$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'];
+ $key = $this->_reformatKey($algorithm, $key);
+
+ switch ($algorithm) {
+ case 'rsaEncryption':
+ $this->publicKey = new RSA();
+ $this->publicKey->loadKey($key);
+ $this->publicKey->setPublicKey();
+ break;
+ default:
+ $this->publicKey = null;
+ }
+
+ $this->currentKeyIdentifier = null;
+ $this->currentCert = $csr;
+
+ return $csr;
+ }
+
+ /**
+ * Save CSR request
+ *
+ * @param array $csr
+ * @param int $format optional
+ * @access public
+ * @return string
+ */
+ function saveCSR($csr, $format = self::FORMAT_PEM)
+ {
+ if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) {
+ return false;
+ }
+
+ switch (true) {
+ case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
+ case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
+ break;
+ default:
+ switch ($algorithm) {
+ case 'rsaEncryption':
+ $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']
+ = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
+ $csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['parameters'] = null;
+ $csr['signatureAlgorithm']['parameters'] = null;
+ $csr['certificationRequestInfo']['signature']['parameters'] = null;
+ }
+ }
+
+ $asn1 = new ASN1();
+
+ $asn1->loadOIDs($this->oids);
+
+ $filters = array();
+ $filters['certificationRequestInfo']['subject']['rdnSequence']['value']
+ = array('type' => ASN1::TYPE_UTF8_STRING);
+
+ $asn1->loadFilters($filters);
+
+ $this->_mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
+ $this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
+ $csr = $asn1->encodeDER($csr, $this->CertificationRequest);
+
+ switch ($format) {
+ case self::FORMAT_DER:
+ return $csr;
+ // case self::FORMAT_PEM:
+ default:
+ return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
+ }
+ }
+
+ /**
+ * Load a SPKAC CSR
+ *
+ * SPKAC's are produced by the HTML5 keygen element:
+ *
+ * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
+ *
+ * @param string $csr
+ * @access public
+ * @return mixed
+ */
+ function loadSPKAC($spkac)
+ {
+ if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) {
+ unset($this->currentCert);
+ unset($this->currentKeyIdentifier);
+ unset($this->signatureSubject);
+ $this->currentCert = $spkac;
+ return $spkac;
+ }
+
+ // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
+
+ $asn1 = new ASN1();
+
+ // OpenSSL produces SPKAC's that are preceded by the string SPKAC=
+ $temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac);
+ $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
+ if ($temp != false) {
+ $spkac = $temp;
+ }
+ $orig = $spkac;
+
+ if ($spkac === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $asn1->loadOIDs($this->oids);
+ $decoded = $asn1->decodeBER($spkac);
+
+ if (empty($decoded)) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $spkac = $asn1->asn1map($decoded[0], $this->SignedPublicKeyAndChallenge);
+
+ if (!isset($spkac) || $spkac === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
+
+ $algorithm = &$spkac['publicKeyAndChallenge']['spki']['algorithm']['algorithm'];
+ $key = &$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'];
+ $key = $this->_reformatKey($algorithm, $key);
+
+ switch ($algorithm) {
+ case 'rsaEncryption':
+ $this->publicKey = new RSA();
+ $this->publicKey->loadKey($key);
+ $this->publicKey->setPublicKey();
+ break;
+ default:
+ $this->publicKey = null;
+ }
+
+ $this->currentKeyIdentifier = null;
+ $this->currentCert = $spkac;
+
+ return $spkac;
+ }
+
+ /**
+ * Save a SPKAC CSR request
+ *
+ * @param array $csr
+ * @param int $format optional
+ * @access public
+ * @return string
+ */
+ function saveSPKAC($spkac, $format = self::FORMAT_PEM)
+ {
+ if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
+ return false;
+ }
+
+ $algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
+ switch (true) {
+ case !$algorithm:
+ case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
+ break;
+ default:
+ switch ($algorithm) {
+ case 'rsaEncryption':
+ $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']
+ = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
+ }
+ }
+
+ $asn1 = new ASN1();
+
+ $asn1->loadOIDs($this->oids);
+ $spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge);
+
+ switch ($format) {
+ case self::FORMAT_DER:
+ return $spkac;
+ // case self::FORMAT_PEM:
+ default:
+ // OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
+ // no other SPKAC decoders phpseclib will use that same format
+ return 'SPKAC=' . base64_encode($spkac);
+ }
+ }
+
+ /**
+ * Load a Certificate Revocation List
+ *
+ * @param string $crl
+ * @access public
+ * @return mixed
+ */
+ function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
+ {
+ if (is_array($crl) && isset($crl['tbsCertList'])) {
+ $this->currentCert = $crl;
+ unset($this->signatureSubject);
+ return $crl;
+ }
+
+ $asn1 = new ASN1();
+
+ if ($mode != self::FORMAT_DER) {
+ $newcrl = $this->_extractBER($crl);
+ if ($mode == self::FORMAT_PEM && $crl == $newcrl) {
+ return false;
+ }
+ $crl = $newcrl;
+ }
+ $orig = $crl;
+
+ if ($crl === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $asn1->loadOIDs($this->oids);
+ $decoded = $asn1->decodeBER($crl);
+
+ if (empty($decoded)) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $crl = $asn1->asn1map($decoded[0], $this->CertificateList);
+ if (!isset($crl) || $crl === false) {
+ $this->currentCert = false;
+ return false;
+ }
+
+ $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
+
+ $this->_mapInDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
+ if ($this->_isSubArrayValid($crl, 'tbsCertList/crlExtensions')) {
+ $this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
+ }
+ if ($this->_isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) {
+ $rclist_ref = &$this->_subArrayUnchecked($crl, 'tbsCertList/revokedCertificates');
+ if ($rclist_ref) {
+ $rclist = $crl['tbsCertList']['revokedCertificates'];
+ foreach ($rclist as $i => $extension) {
+ if ($this->_isSubArrayValid($rclist, "$i/crlEntryExtensions", $asn1)) {
+ $this->_mapInExtensions($rclist_ref, "$i/crlEntryExtensions", $asn1);
+ }
+ }
+ }
+ }
+
+ $this->currentKeyIdentifier = null;
+ $this->currentCert = $crl;
+
+ return $crl;
+ }
+
+ /**
+ * Save Certificate Revocation List.
+ *
+ * @param array $crl
+ * @param int $format optional
+ * @access public
+ * @return string
+ */
+ function saveCRL($crl, $format = self::FORMAT_PEM)
+ {
+ if (!is_array($crl) || !isset($crl['tbsCertList'])) {
+ return false;
+ }
+
+ $asn1 = new ASN1();
+
+ $asn1->loadOIDs($this->oids);
+
+ $filters = array();
+ $filters['tbsCertList']['issuer']['rdnSequence']['value']
+ = array('type' => ASN1::TYPE_UTF8_STRING);
+ $filters['tbsCertList']['signature']['parameters']
+ = array('type' => ASN1::TYPE_UTF8_STRING);
+ $filters['signatureAlgorithm']['parameters']
+ = array('type' => ASN1::TYPE_UTF8_STRING);
+
+ if (empty($crl['tbsCertList']['signature']['parameters'])) {
+ $filters['tbsCertList']['signature']['parameters']
+ = array('type' => ASN1::TYPE_NULL);
+ }
+
+ if (empty($crl['signatureAlgorithm']['parameters'])) {
+ $filters['signatureAlgorithm']['parameters']
+ = array('type' => ASN1::TYPE_NULL);
+ }
+
+ $asn1->loadFilters($filters);
+
+ $this->_mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
+ $this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
+ $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
+ if (is_array($rclist)) {
+ foreach ($rclist as $i => $extension) {
+ $this->_mapOutExtensions($rclist, "$i/crlEntryExtensions", $asn1);
+ }
+ }
+
+ $crl = $asn1->encodeDER($crl, $this->CertificateList);
+
+ switch ($format) {
+ case self::FORMAT_DER:
+ return $crl;
+ // case self::FORMAT_PEM:
+ default:
+ return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----';
+ }
+ }
+
+ /**
+ * Helper function to build a time field according to RFC 3280 section
+ * - 4.1.2.5 Validity
+ * - 5.1.2.4 This Update
+ * - 5.1.2.5 Next Update
+ * - 5.1.2.6 Revoked Certificates
+ * by choosing utcTime iff year of date given is before 2050 and generalTime else.
+ *
+ * @param string $date in format date('D, d M Y H:i:s O')
+ * @access private
+ * @return array
+ */
+ function _timeField($date)
+ {
+ if ($date instanceof Element) {
+ return $date;
+ }
+ $dateObj = new DateTime($date, new DateTimeZone('GMT'));
+ $year = $dateObj->format('Y'); // the same way ASN1.php parses this
+ if ($year < 2050) {
+ return array('utcTime' => $date);
+ } else {
+ return array('generalTime' => $date);
+ }
+ }
+
+ /**
+ * Sign an X.509 certificate
+ *
+ * $issuer's private key needs to be loaded.
+ * $subject can be either an existing X.509 cert (if you want to resign it),
+ * a CSR or something with the DN and public key explicitly set.
+ *
+ * @param \phpseclib\File\X509 $issuer
+ * @param \phpseclib\File\X509 $subject
+ * @param string $signatureAlgorithm optional
+ * @access public
+ * @return mixed
+ */
+ function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption')
+ {
+ if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
+ return false;
+ }
+
+ if (isset($subject->publicKey) && !($subjectPublicKey = $subject->_formatSubjectPublicKey())) {
+ return false;
+ }
+
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
+
+ if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) {
+ $this->currentCert = $subject->currentCert;
+ $this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm;
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
+
+ if (!empty($this->startDate)) {
+ $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate);
+ }
+ if (!empty($this->endDate)) {
+ $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate);
+ }
+ if (!empty($this->serialNumber)) {
+ $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
+ }
+ if (!empty($subject->dn)) {
+ $this->currentCert['tbsCertificate']['subject'] = $subject->dn;
+ }
+ if (!empty($subject->publicKey)) {
+ $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey;
+ }
+ $this->removeExtension('id-ce-authorityKeyIdentifier');
+ if (isset($subject->domains)) {
+ $this->removeExtension('id-ce-subjectAltName');
+ }
+ } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
+ return false;
+ } else {
+ if (!isset($subject->publicKey)) {
+ return false;
+ }
+
+ $startDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
+ $startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
+
+ $endDate = new DateTime('+1 year', new DateTimeZone(@date_default_timezone_get()));
+ $endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
+
+ /* "The serial number MUST be a positive integer"
+ "Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
+ -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
+
+ for the integer to be positive the leading bit needs to be 0 hence the
+ application of a bitmap
+ */
+ $serialNumber = !empty($this->serialNumber) ?
+ $this->serialNumber :
+ new BigInteger(Random::string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256);
+
+ $this->currentCert = array(
+ 'tbsCertificate' =>
+ array(
+ 'version' => 'v3',
+ 'serialNumber' => $serialNumber, // $this->setSerialNumber()
+ 'signature' => array('algorithm' => $signatureAlgorithm),
+ 'issuer' => false, // this is going to be overwritten later
+ 'validity' => array(
+ 'notBefore' => $this->_timeField($startDate), // $this->setStartDate()
+ 'notAfter' => $this->_timeField($endDate) // $this->setEndDate()
+ ),
+ 'subject' => $subject->dn,
+ 'subjectPublicKeyInfo' => $subjectPublicKey
+ ),
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
+ 'signature' => false // this is going to be overwritten later
+ );
+
+ // Copy extensions from CSR.
+ $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);
+
+ if (!empty($csrexts)) {
+ $this->currentCert['tbsCertificate']['extensions'] = $csrexts;
+ }
+ }
+
+ $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn;
+
+ if (isset($issuer->currentKeyIdentifier)) {
+ $this->setExtension('id-ce-authorityKeyIdentifier', array(
+ //'authorityCertIssuer' => array(
+ // array(
+ // 'directoryName' => $issuer->dn
+ // )
+ //),
+ 'keyIdentifier' => $issuer->currentKeyIdentifier
+ ));
+ //$extensions = &$this->currentCert['tbsCertificate']['extensions'];
+ //if (isset($issuer->serialNumber)) {
+ // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
+ //}
+ //unset($extensions);
+ }
+
+ if (isset($subject->currentKeyIdentifier)) {
+ $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier);
+ }
+
+ $altName = array();
+
+ if (isset($subject->domains) && count($subject->domains)) {
+ $altName = array_map(array('\phpseclib\File\X509', '_dnsName'), $subject->domains);
+ }
+
+ if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
+ // should an IP address appear as the CN if no domain name is specified? idk
+ //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
+ $ipAddresses = array();
+ foreach ($subject->ipAddresses as $ipAddress) {
+ $encoded = $subject->_ipAddress($ipAddress);
+ if ($encoded !== false) {
+ $ipAddresses[] = $encoded;
+ }
+ }
+ if (count($ipAddresses)) {
+ $altName = array_merge($altName, $ipAddresses);
+ }
+ }
+
+ if (!empty($altName)) {
+ $this->setExtension('id-ce-subjectAltName', $altName);
+ }
+
+ if ($this->caFlag) {
+ $keyUsage = $this->getExtension('id-ce-keyUsage');
+ if (!$keyUsage) {
+ $keyUsage = array();
+ }
+
+ $this->setExtension(
+ 'id-ce-keyUsage',
+ array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign'))))
+ );
+
+ $basicConstraints = $this->getExtension('id-ce-basicConstraints');
+ if (!$basicConstraints) {
+ $basicConstraints = array();
+ }
+
+ $this->setExtension(
+ 'id-ce-basicConstraints',
+ array_unique(array_merge(array('cA' => true), $basicConstraints)),
+ true
+ );
+
+ if (!isset($subject->currentKeyIdentifier)) {
+ $this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false);
+ }
+ }
+
+ // resync $this->signatureSubject
+ // save $tbsCertificate in case there are any \phpseclib\File\ASN1\Element objects in it
+ $tbsCertificate = $this->currentCert['tbsCertificate'];
+ $this->loadX509($this->saveX509($this->currentCert));
+
+ $result = $this->_sign($issuer->privateKey, $signatureAlgorithm);
+ $result['tbsCertificate'] = $tbsCertificate;
+
+ $this->currentCert = $currentCert;
+ $this->signatureSubject = $signatureSubject;
+
+ return $result;
+ }
+
+ /**
+ * Sign a CSR
+ *
+ * @access public
+ * @return mixed
+ */
+ function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption')
+ {
+ if (!is_object($this->privateKey) || empty($this->dn)) {
+ return false;
+ }
+
+ $origPublicKey = $this->publicKey;
+ $class = get_class($this->privateKey);
+ $this->publicKey = new $class();
+ $this->publicKey->loadKey($this->privateKey->getPublicKey());
+ $this->publicKey->setPublicKey();
+ if (!($publicKey = $this->_formatSubjectPublicKey())) {
+ return false;
+ }
+ $this->publicKey = $origPublicKey;
+
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
+
+ if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) {
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
+ if (!empty($this->dn)) {
+ $this->currentCert['certificationRequestInfo']['subject'] = $this->dn;
+ }
+ $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey;
+ } else {
+ $this->currentCert = array(
+ 'certificationRequestInfo' =>
+ array(
+ 'version' => 'v1',
+ 'subject' => $this->dn,
+ 'subjectPKInfo' => $publicKey
+ ),
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
+ 'signature' => false // this is going to be overwritten later
+ );
+ }
+
+ // resync $this->signatureSubject
+ // save $certificationRequestInfo in case there are any \phpseclib\File\ASN1\Element objects in it
+ $certificationRequestInfo = $this->currentCert['certificationRequestInfo'];
+ $this->loadCSR($this->saveCSR($this->currentCert));
+
+ $result = $this->_sign($this->privateKey, $signatureAlgorithm);
+ $result['certificationRequestInfo'] = $certificationRequestInfo;
+
+ $this->currentCert = $currentCert;
+ $this->signatureSubject = $signatureSubject;
+
+ return $result;
+ }
+
+ /**
+ * Sign a SPKAC
+ *
+ * @access public
+ * @return mixed
+ */
+ function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption')
+ {
+ if (!is_object($this->privateKey)) {
+ return false;
+ }
+
+ $origPublicKey = $this->publicKey;
+ $class = get_class($this->privateKey);
+ $this->publicKey = new $class();
+ $this->publicKey->loadKey($this->privateKey->getPublicKey());
+ $this->publicKey->setPublicKey();
+ $publicKey = $this->_formatSubjectPublicKey();
+ if (!$publicKey) {
+ return false;
+ }
+ $this->publicKey = $origPublicKey;
+
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
+
+ // re-signing a SPKAC seems silly but since everything else supports re-signing why not?
+ if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) {
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
+ $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey;
+ if (!empty($this->challenge)) {
+ // the bitwise AND ensures that the output is a valid IA5String
+ $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge));
+ }
+ } else {
+ $this->currentCert = array(
+ 'publicKeyAndChallenge' =>
+ array(
+ 'spki' => $publicKey,
+ // quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
+ // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
+ // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
+ // we could alternatively do this instead if we ignored the specs:
+ // Random::string(8) & str_repeat("\x7F", 8)
+ 'challenge' => !empty($this->challenge) ? $this->challenge : ''
+ ),
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
+ 'signature' => false // this is going to be overwritten later
+ );
+ }
+
+ // resync $this->signatureSubject
+ // save $publicKeyAndChallenge in case there are any \phpseclib\File\ASN1\Element objects in it
+ $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
+ $this->loadSPKAC($this->saveSPKAC($this->currentCert));
+
+ $result = $this->_sign($this->privateKey, $signatureAlgorithm);
+ $result['publicKeyAndChallenge'] = $publicKeyAndChallenge;
+
+ $this->currentCert = $currentCert;
+ $this->signatureSubject = $signatureSubject;
+
+ return $result;
+ }
+
+ /**
+ * Sign a CRL
+ *
+ * $issuer's private key needs to be loaded.
+ *
+ * @param \phpseclib\File\X509 $issuer
+ * @param \phpseclib\File\X509 $crl
+ * @param string $signatureAlgorithm optional
+ * @access public
+ * @return mixed
+ */
+ function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption')
+ {
+ if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
+ return false;
+ }
+
+ $currentCert = isset($this->currentCert) ? $this->currentCert : null;
+ $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
+
+ $thisUpdate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
+ $thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
+
+ if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
+ $this->currentCert = $crl->currentCert;
+ $this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm;
+ $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
+ } else {
+ $this->currentCert = array(
+ 'tbsCertList' =>
+ array(
+ 'version' => 'v2',
+ 'signature' => array('algorithm' => $signatureAlgorithm),
+ 'issuer' => false, // this is going to be overwritten later
+ 'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
+ ),
+ 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
+ 'signature' => false // this is going to be overwritten later
+ );
+ }
+
+ $tbsCertList = &$this->currentCert['tbsCertList'];
+ $tbsCertList['issuer'] = $issuer->dn;
+ $tbsCertList['thisUpdate'] = $this->_timeField($thisUpdate);
+
+ if (!empty($this->endDate)) {
+ $tbsCertList['nextUpdate'] = $this->_timeField($this->endDate); // $this->setEndDate()
+ } else {
+ unset($tbsCertList['nextUpdate']);
+ }
+
+ if (!empty($this->serialNumber)) {
+ $crlNumber = $this->serialNumber;
+ } else {
+ $crlNumber = $this->getExtension('id-ce-cRLNumber');
+ // "The CRL number is a non-critical CRL extension that conveys a
+ // monotonically increasing sequence number for a given CRL scope and
+ // CRL issuer. This extension allows users to easily determine when a
+ // particular CRL supersedes another CRL."
+ // -- https://tools.ietf.org/html/rfc5280#section-5.2.3
+ $crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null;
+ }
+
+ $this->removeExtension('id-ce-authorityKeyIdentifier');
+ $this->removeExtension('id-ce-issuerAltName');
+
+ // Be sure version >= v2 if some extension found.
+ $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0;
+ if (!$version) {
+ if (!empty($tbsCertList['crlExtensions'])) {
+ $version = 1; // v2.
+ } elseif (!empty($tbsCertList['revokedCertificates'])) {
+ foreach ($tbsCertList['revokedCertificates'] as $cert) {
+ if (!empty($cert['crlEntryExtensions'])) {
+ $version = 1; // v2.
+ }
+ }
+ }
+
+ if ($version) {
+ $tbsCertList['version'] = $version;
+ }
+ }
+
+ // Store additional extensions.
+ if (!empty($tbsCertList['version'])) { // At least v2.
+ if (!empty($crlNumber)) {
+ $this->setExtension('id-ce-cRLNumber', $crlNumber);
+ }
+
+ if (isset($issuer->currentKeyIdentifier)) {
+ $this->setExtension('id-ce-authorityKeyIdentifier', array(
+ //'authorityCertIssuer' => array(
+ // array(
+ // 'directoryName' => $issuer->dn
+ // )
+ //),
+ 'keyIdentifier' => $issuer->currentKeyIdentifier
+ ));
+ //$extensions = &$tbsCertList['crlExtensions'];
+ //if (isset($issuer->serialNumber)) {
+ // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
+ //}
+ //unset($extensions);
+ }
+
+ $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert);
+
+ if ($issuerAltName !== false) {
+ $this->setExtension('id-ce-issuerAltName', $issuerAltName);
+ }
+ }
+
+ if (empty($tbsCertList['revokedCertificates'])) {
+ unset($tbsCertList['revokedCertificates']);
+ }
+
+ unset($tbsCertList);
+
+ // resync $this->signatureSubject
+ // save $tbsCertList in case there are any \phpseclib\File\ASN1\Element objects in it
+ $tbsCertList = $this->currentCert['tbsCertList'];
+ $this->loadCRL($this->saveCRL($this->currentCert));
+
+ $result = $this->_sign($issuer->privateKey, $signatureAlgorithm);
+ $result['tbsCertList'] = $tbsCertList;
+
+ $this->currentCert = $currentCert;
+ $this->signatureSubject = $signatureSubject;
+
+ return $result;
+ }
+
+ /**
+ * X.509 certificate signing helper function.
+ *
+ * @param object $key
+ * @param \phpseclib\File\X509 $subject
+ * @param string $signatureAlgorithm
+ * @access public
+ * @return mixed
+ */
+ function _sign($key, $signatureAlgorithm)
+ {
+ if ($key instanceof RSA) {
+ switch ($signatureAlgorithm) {
+ case 'md2WithRSAEncryption':
+ case 'md5WithRSAEncryption':
+ case 'sha1WithRSAEncryption':
+ case 'sha224WithRSAEncryption':
+ case 'sha256WithRSAEncryption':
+ case 'sha384WithRSAEncryption':
+ case 'sha512WithRSAEncryption':
+ $key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
+ $key->setSignatureMode(RSA::SIGNATURE_PKCS1);
+
+ $this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
+ return $this->currentCert;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set certificate start date
+ *
+ * @param string $date
+ * @access public
+ */
+ function setStartDate($date)
+ {
+ if (!is_object($date) || !is_a($date, 'DateTime')) {
+ $date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
+ }
+
+ $this->startDate = $date->format('D, d M Y H:i:s O');
+ }
+
+ /**
+ * Set certificate end date
+ *
+ * @param string $date
+ * @access public
+ */
+ function setEndDate($date)
+ {
+ /*
+ To indicate that a certificate has no well-defined expiration date,
+ the notAfter SHOULD be assigned the GeneralizedTime value of
+ 99991231235959Z.
+
+ -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5
+ */
+ if (strtolower($date) == 'lifetime') {
+ $temp = '99991231235959Z';
+ $asn1 = new ASN1();
+ $temp = chr(ASN1::TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
+ $this->endDate = new Element($temp);
+ } else {
+ if (!is_object($date) || !is_a($date, 'DateTime')) {
+ $date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
+ }
+
+ $this->endDate = $date->format('D, d M Y H:i:s O');
+ }
+ }
+
+ /**
+ * Set Serial Number
+ *
+ * @param string $serial
+ * @param $base optional
+ * @access public
+ */
+ function setSerialNumber($serial, $base = -256)
+ {
+ $this->serialNumber = new BigInteger($serial, $base);
+ }
+
+ /**
+ * Turns the certificate into a certificate authority
+ *
+ * @access public
+ */
+ function makeCA()
+ {
+ $this->caFlag = true;
+ }
+
+ /**
+ * Check for validity of subarray
+ *
+ * This is intended for use in conjunction with _subArrayUnchecked(),
+ * implementing the checks included in _subArray() but without copying
+ * a potentially large array by passing its reference by-value to is_array().
+ *
+ * @param array $root
+ * @param string $path
+ * @return boolean
+ * @access private
+ */
+ function _isSubArrayValid($root, $path)
+ {
+ if (!is_array($root)) {
+ return false;
+ }
+
+ foreach (explode('/', $path) as $i) {
+ if (!is_array($root)) {
+ return false;
+ }
+
+ if (!isset($root[$i])) {
+ return true;
+ }
+
+ $root = $root[$i];
+ }
+
+ return true;
+ }
+
+ /**
+ * Get a reference to a subarray
+ *
+ * This variant of _subArray() does no is_array() checking,
+ * so $root should be checked with _isSubArrayValid() first.
+ *
+ * This is here for performance reasons:
+ * Passing a reference (i.e. $root) by-value (i.e. to is_array())
+ * creates a copy. If $root is an especially large array, this is expensive.
+ *
+ * @param array $root
+ * @param string $path absolute path with / as component separator
+ * @param bool $create optional
+ * @access private
+ * @return array|false
+ */
+ function &_subArrayUnchecked(&$root, $path, $create = false)
+ {
+ $false = false;
+
+ foreach (explode('/', $path) as $i) {
+ if (!isset($root[$i])) {
+ if (!$create) {
+ return $false;
+ }
+
+ $root[$i] = array();
+ }
+
+ $root = &$root[$i];
+ }
+
+ return $root;
+ }
+
+ /**
+ * Get a reference to a subarray
+ *
+ * @param array $root
+ * @param string $path absolute path with / as component separator
+ * @param bool $create optional
+ * @access private
+ * @return array|false
+ */
+ function &_subArray(&$root, $path, $create = false)
+ {
+ $false = false;
+
+ if (!is_array($root)) {
+ return $false;
+ }
+
+ foreach (explode('/', $path) as $i) {
+ if (!is_array($root)) {
+ return $false;
+ }
+
+ if (!isset($root[$i])) {
+ if (!$create) {
+ return $false;
+ }
+
+ $root[$i] = array();
+ }
+
+ $root = &$root[$i];
+ }
+
+ return $root;
+ }
+
+ /**
+ * Get a reference to an extension subarray
+ *
+ * @param array $root
+ * @param string $path optional absolute path with / as component separator
+ * @param bool $create optional
+ * @access private
+ * @return array|false
+ */
+ function &_extensions(&$root, $path = null, $create = false)
+ {
+ if (!isset($root)) {
+ $root = $this->currentCert;
+ }
+
+ switch (true) {
+ case !empty($path):
+ case !is_array($root):
+ break;
+ case isset($root['tbsCertificate']):
+ $path = 'tbsCertificate/extensions';
+ break;
+ case isset($root['tbsCertList']):
+ $path = 'tbsCertList/crlExtensions';
+ break;
+ case isset($root['certificationRequestInfo']):
+ $pth = 'certificationRequestInfo/attributes';
+ $attributes = &$this->_subArray($root, $pth, $create);
+
+ if (is_array($attributes)) {
+ foreach ($attributes as $key => $value) {
+ if ($value['type'] == 'pkcs-9-at-extensionRequest') {
+ $path = "$pth/$key/value/0";
+ break 2;
+ }
+ }
+ if ($create) {
+ $key = count($attributes);
+ $attributes[] = array('type' => 'pkcs-9-at-extensionRequest', 'value' => array());
+ $path = "$pth/$key/value/0";
+ }
+ }
+ break;
+ }
+
+ $extensions = &$this->_subArray($root, $path, $create);
+
+ if (!is_array($extensions)) {
+ $false = false;
+ return $false;
+ }
+
+ return $extensions;
+ }
+
+ /**
+ * Remove an Extension
+ *
+ * @param string $id
+ * @param string $path optional
+ * @access private
+ * @return bool
+ */
+ function _removeExtension($id, $path = null)
+ {
+ $extensions = &$this->_extensions($this->currentCert, $path);
+
+ if (!is_array($extensions)) {
+ return false;
+ }
+
+ $result = false;
+ foreach ($extensions as $key => $value) {
+ if ($value['extnId'] == $id) {
+ unset($extensions[$key]);
+ $result = true;
+ }
+ }
+
+ $extensions = array_values($extensions);
+ // fix for https://bugs.php.net/75433 affecting PHP 7.2
+ if (!isset($extensions[0])) {
+ $extensions = array_splice($extensions, 0, 0);
+ }
+ return $result;
+ }
+
+ /**
+ * Get an Extension
+ *
+ * Returns the extension if it exists and false if not
+ *
+ * @param string $id
+ * @param array $cert optional
+ * @param string $path optional
+ * @access private
+ * @return mixed
+ */
+ function _getExtension($id, $cert = null, $path = null)
+ {
+ $extensions = $this->_extensions($cert, $path);
+
+ if (!is_array($extensions)) {
+ return false;
+ }
+
+ foreach ($extensions as $key => $value) {
+ if ($value['extnId'] == $id) {
+ return $value['extnValue'];
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a list of all extensions in use
+ *
+ * @param array $cert optional
+ * @param string $path optional
+ * @access private
+ * @return array
+ */
+ function _getExtensions($cert = null, $path = null)
+ {
+ $exts = $this->_extensions($cert, $path);
+ $extensions = array();
+
+ if (is_array($exts)) {
+ foreach ($exts as $extension) {
+ $extensions[] = $extension['extnId'];
+ }
+ }
+
+ return $extensions;
+ }
+
+ /**
+ * Set an Extension
+ *
+ * @param string $id
+ * @param mixed $value
+ * @param bool $critical optional
+ * @param bool $replace optional
+ * @param string $path optional
+ * @access private
+ * @return bool
+ */
+ function _setExtension($id, $value, $critical = false, $replace = true, $path = null)
+ {
+ $extensions = &$this->_extensions($this->currentCert, $path, true);
+
+ if (!is_array($extensions)) {
+ return false;
+ }
+
+ $newext = array('extnId' => $id, 'critical' => $critical, 'extnValue' => $value);
+
+ foreach ($extensions as $key => $value) {
+ if ($value['extnId'] == $id) {
+ if (!$replace) {
+ return false;
+ }
+
+ $extensions[$key] = $newext;
+ return true;
+ }
+ }
+
+ $extensions[] = $newext;
+ return true;
+ }
+
+ /**
+ * Remove a certificate, CSR or CRL Extension
+ *
+ * @param string $id
+ * @access public
+ * @return bool
+ */
+ function removeExtension($id)
+ {
+ return $this->_removeExtension($id);
+ }
+
+ /**
+ * Get a certificate, CSR or CRL Extension
+ *
+ * Returns the extension if it exists and false if not
+ *
+ * @param string $id
+ * @param array $cert optional
+ * @access public
+ * @return mixed
+ */
+ function getExtension($id, $cert = null)
+ {
+ return $this->_getExtension($id, $cert);
+ }
+
+ /**
+ * Returns a list of all extensions in use in certificate, CSR or CRL
+ *
+ * @param array $cert optional
+ * @access public
+ * @return array
+ */
+ function getExtensions($cert = null)
+ {
+ return $this->_getExtensions($cert);
+ }
+
+ /**
+ * Set a certificate, CSR or CRL Extension
+ *
+ * @param string $id
+ * @param mixed $value
+ * @param bool $critical optional
+ * @param bool $replace optional
+ * @access public
+ * @return bool
+ */
+ function setExtension($id, $value, $critical = false, $replace = true)
+ {
+ return $this->_setExtension($id, $value, $critical, $replace);
+ }
+
+ /**
+ * Remove a CSR attribute.
+ *
+ * @param string $id
+ * @param int $disposition optional
+ * @access public
+ * @return bool
+ */
+ function removeAttribute($id, $disposition = self::ATTR_ALL)
+ {
+ $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes');
+
+ if (!is_array($attributes)) {
+ return false;
+ }
+
+ $result = false;
+ foreach ($attributes as $key => $attribute) {
+ if ($attribute['type'] == $id) {
+ $n = count($attribute['value']);
+ switch (true) {
+ case $disposition == self::ATTR_APPEND:
+ case $disposition == self::ATTR_REPLACE:
+ return false;
+ case $disposition >= $n:
+ $disposition -= $n;
+ break;
+ case $disposition == self::ATTR_ALL:
+ case $n == 1:
+ unset($attributes[$key]);
+ $result = true;
+ break;
+ default:
+ unset($attributes[$key]['value'][$disposition]);
+ $attributes[$key]['value'] = array_values($attributes[$key]['value']);
+ $result = true;
+ break;
+ }
+ if ($result && $disposition != self::ATTR_ALL) {
+ break;
+ }
+ }
+ }
+
+ $attributes = array_values($attributes);
+ return $result;
+ }
+
+ /**
+ * Get a CSR attribute
+ *
+ * Returns the attribute if it exists and false if not
+ *
+ * @param string $id
+ * @param int $disposition optional
+ * @param array $csr optional
+ * @access public
+ * @return mixed
+ */
+ function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
+ {
+ if (empty($csr)) {
+ $csr = $this->currentCert;
+ }
+
+ $attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes');
+
+ if (!is_array($attributes)) {
+ return false;
+ }
+
+ foreach ($attributes as $key => $attribute) {
+ if ($attribute['type'] == $id) {
+ $n = count($attribute['value']);
+ switch (true) {
+ case $disposition == self::ATTR_APPEND:
+ case $disposition == self::ATTR_REPLACE:
+ return false;
+ case $disposition == self::ATTR_ALL:
+ return $attribute['value'];
+ case $disposition >= $n:
+ $disposition -= $n;
+ break;
+ default:
+ return $attribute['value'][$disposition];
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a list of all CSR attributes in use
+ *
+ * @param array $csr optional
+ * @access public
+ * @return array
+ */
+ function getAttributes($csr = null)
+ {
+ if (empty($csr)) {
+ $csr = $this->currentCert;
+ }
+
+ $attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes');
+ $attrs = array();
+
+ if (is_array($attributes)) {
+ foreach ($attributes as $attribute) {
+ $attrs[] = $attribute['type'];
+ }
+ }
+
+ return $attrs;
+ }
+
+ /**
+ * Set a CSR attribute
+ *
+ * @param string $id
+ * @param mixed $value
+ * @param bool $disposition optional
+ * @access public
+ * @return bool
+ */
+ function setAttribute($id, $value, $disposition = self::ATTR_ALL)
+ {
+ $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
+
+ if (!is_array($attributes)) {
+ return false;
+ }
+
+ switch ($disposition) {
+ case self::ATTR_REPLACE:
+ $disposition = self::ATTR_APPEND;
+ case self::ATTR_ALL:
+ $this->removeAttribute($id);
+ break;
+ }
+
+ foreach ($attributes as $key => $attribute) {
+ if ($attribute['type'] == $id) {
+ $n = count($attribute['value']);
+ switch (true) {
+ case $disposition == self::ATTR_APPEND:
+ $last = $key;
+ break;
+ case $disposition >= $n:
+ $disposition -= $n;
+ break;
+ default:
+ $attributes[$key]['value'][$disposition] = $value;
+ return true;
+ }
+ }
+ }
+
+ switch (true) {
+ case $disposition >= 0:
+ return false;
+ case isset($last):
+ $attributes[$last]['value'][] = $value;
+ break;
+ default:
+ $attributes[] = array('type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value: array($value));
+ break;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the subject key identifier
+ *
+ * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions.
+ *
+ * @param string $value
+ * @access public
+ */
+ function setKeyIdentifier($value)
+ {
+ if (empty($value)) {
+ unset($this->currentKeyIdentifier);
+ } else {
+ $this->currentKeyIdentifier = base64_encode($value);
+ }
+ }
+
+ /**
+ * Compute a public key identifier.
+ *
+ * Although key identifiers may be set to any unique value, this function
+ * computes key identifiers from public key according to the two
+ * recommended methods (4.2.1.2 RFC 3280).
+ * Highly polymorphic: try to accept all possible forms of key:
+ * - Key object
+ * - \phpseclib\File\X509 object with public or private key defined
+ * - Certificate or CSR array
+ * - \phpseclib\File\ASN1\Element object
+ * - PEM or DER string
+ *
+ * @param mixed $key optional
+ * @param int $method optional
+ * @access public
+ * @return string binary key identifier
+ */
+ function computeKeyIdentifier($key = null, $method = 1)
+ {
+ if (is_null($key)) {
+ $key = $this;
+ }
+
+ switch (true) {
+ case is_string($key):
+ break;
+ case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
+ return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method);
+ case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
+ return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method);
+ case !is_object($key):
+ return false;
+ case $key instanceof Element:
+ // Assume the element is a bitstring-packed key.
+ $asn1 = new ASN1();
+ $decoded = $asn1->decodeBER($key->element);
+ if (empty($decoded)) {
+ return false;
+ }
+ $raw = $asn1->asn1map($decoded[0], array('type' => ASN1::TYPE_BIT_STRING));
+ if (empty($raw)) {
+ return false;
+ }
+ $raw = base64_decode($raw);
+ // If the key is private, compute identifier from its corresponding public key.
+ $key = new RSA();
+ if (!$key->loadKey($raw)) {
+ return false; // Not an unencrypted RSA key.
+ }
+ if ($key->getPrivateKey() !== false) { // If private.
+ return $this->computeKeyIdentifier($key, $method);
+ }
+ $key = $raw; // Is a public key.
+ break;
+ case $key instanceof X509:
+ if (isset($key->publicKey)) {
+ return $this->computeKeyIdentifier($key->publicKey, $method);
+ }
+ if (isset($key->privateKey)) {
+ return $this->computeKeyIdentifier($key->privateKey, $method);
+ }
+ if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) {
+ return $this->computeKeyIdentifier($key->currentCert, $method);
+ }
+ return false;
+ default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA).
+ $key = $key->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
+ break;
+ }
+
+ // If in PEM format, convert to binary.
+ $key = $this->_extractBER($key);
+
+ // Now we have the key string: compute its sha-1 sum.
+ $hash = new Hash('sha1');
+ $hash = $hash->hash($key);
+
+ if ($method == 2) {
+ $hash = substr($hash, -8);
+ $hash[0] = chr((ord($hash[0]) & 0x0F) | 0x40);
+ }
+
+ return $hash;
+ }
+
+ /**
+ * Format a public key as appropriate
+ *
+ * @access private
+ * @return array
+ */
+ function _formatSubjectPublicKey()
+ {
+ if ($this->publicKey instanceof RSA) {
+ // the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
+ // the former is a good example of how to do fuzzing on the public key
+ //return new Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
+ return array(
+ 'algorithm' => array('algorithm' => 'rsaEncryption'),
+ 'subjectPublicKey' => $this->publicKey->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1)
+ );
+ }
+
+ return false;
+ }
+
+ /**
+ * Set the domain name's which the cert is to be valid for
+ *
+ * @access public
+ * @return array
+ */
+ function setDomain()
+ {
+ $this->domains = func_get_args();
+ $this->removeDNProp('id-at-commonName');
+ $this->setDNProp('id-at-commonName', $this->domains[0]);
+ }
+
+ /**
+ * Set the IP Addresses's which the cert is to be valid for
+ *
+ * @access public
+ * @param string $ipAddress optional
+ */
+ function setIPAddress()
+ {
+ $this->ipAddresses = func_get_args();
+ /*
+ if (!isset($this->domains)) {
+ $this->removeDNProp('id-at-commonName');
+ $this->setDNProp('id-at-commonName', $this->ipAddresses[0]);
+ }
+ */
+ }
+
+ /**
+ * Helper function to build domain array
+ *
+ * @access private
+ * @param string $domain
+ * @return array
+ */
+ function _dnsName($domain)
+ {
+ return array('dNSName' => $domain);
+ }
+
+ /**
+ * Helper function to build IP Address array
+ *
+ * (IPv6 is not currently supported)
+ *
+ * @access private
+ * @param string $address
+ * @return array
+ */
+ function _iPAddress($address)
+ {
+ return array('iPAddress' => $address);
+ }
+
+ /**
+ * Get the index of a revoked certificate.
+ *
+ * @param array $rclist
+ * @param string $serial
+ * @param bool $create optional
+ * @access private
+ * @return int|false
+ */
+ function _revokedCertificate(&$rclist, $serial, $create = false)
+ {
+ $serial = new BigInteger($serial);
+
+ foreach ($rclist as $i => $rc) {
+ if (!($serial->compare($rc['userCertificate']))) {
+ return $i;
+ }
+ }
+
+ if (!$create) {
+ return false;
+ }
+
+ $i = count($rclist);
+ $revocationDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
+ $rclist[] = array('userCertificate' => $serial,
+ 'revocationDate' => $this->_timeField($revocationDate->format('D, d M Y H:i:s O')));
+ return $i;
+ }
+
+ /**
+ * Revoke a certificate.
+ *
+ * @param string $serial
+ * @param string $date optional
+ * @access public
+ * @return bool
+ */
+ function revoke($serial, $date = null)
+ {
+ if (isset($this->currentCert['tbsCertList'])) {
+ if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
+ if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked
+ if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
+ if (!empty($date)) {
+ $rclist[$i]['revocationDate'] = $this->_timeField($date);
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Unrevoke a certificate.
+ *
+ * @param string $serial
+ * @access public
+ * @return bool
+ */
+ function unrevoke($serial)
+ {
+ if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
+ unset($rclist[$i]);
+ $rclist = array_values($rclist);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get a revoked certificate.
+ *
+ * @param string $serial
+ * @access public
+ * @return mixed
+ */
+ function getRevoked($serial)
+ {
+ if (is_array($rclist = $this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
+ return $rclist[$i];
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * List revoked certificates
+ *
+ * @param array $crl optional
+ * @access public
+ * @return array
+ */
+ function listRevoked($crl = null)
+ {
+ if (!isset($crl)) {
+ $crl = $this->currentCert;
+ }
+
+ if (!isset($crl['tbsCertList'])) {
+ return false;
+ }
+
+ $result = array();
+
+ if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
+ foreach ($rclist as $rc) {
+ $result[] = $rc['userCertificate']->toString();
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Remove a Revoked Certificate Extension
+ *
+ * @param string $serial
+ * @param string $id
+ * @access public
+ * @return bool
+ */
+ function removeRevokedCertificateExtension($serial, $id)
+ {
+ if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
+ return $this->_removeExtension($id, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get a Revoked Certificate Extension
+ *
+ * Returns the extension if it exists and false if not
+ *
+ * @param string $serial
+ * @param string $id
+ * @param array $crl optional
+ * @access public
+ * @return mixed
+ */
+ function getRevokedCertificateExtension($serial, $id, $crl = null)
+ {
+ if (!isset($crl)) {
+ $crl = $this->currentCert;
+ }
+
+ if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
+ return $this->_getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a list of all extensions in use for a given revoked certificate
+ *
+ * @param string $serial
+ * @param array $crl optional
+ * @access public
+ * @return array
+ */
+ function getRevokedCertificateExtensions($serial, $crl = null)
+ {
+ if (!isset($crl)) {
+ $crl = $this->currentCert;
+ }
+
+ if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
+ if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
+ return $this->_getExtensions($crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set a Revoked Certificate Extension
+ *
+ * @param string $serial
+ * @param string $id
+ * @param mixed $value
+ * @param bool $critical optional
+ * @param bool $replace optional
+ * @access public
+ * @return bool
+ */
+ function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
+ {
+ if (isset($this->currentCert['tbsCertList'])) {
+ if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
+ if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
+ return $this->_setExtension($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Extract raw BER from Base64 encoding
+ *
+ * @access private
+ * @param string $str
+ * @return string
+ */
+ function _extractBER($str)
+ {
+ /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
+ * above and beyond the ceritificate.
+ * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
+ *
+ * Bag Attributes
+ * localKeyID: 01 00 00 00
+ * subject=/O=organization/OU=org unit/CN=common name
+ * issuer=/O=organization/CN=common name
+ */
+ $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
+ // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
+ $temp = preg_replace('#-+[^-]+-+#', '', $temp);
+ // remove new lines
+ $temp = str_replace(array("\r", "\n", ' '), '', $temp);
+ $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
+ return $temp != false ? $temp : $str;
+ }
+
+ /**
+ * Returns the OID corresponding to a name
+ *
+ * What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if
+ * no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version
+ * of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able
+ * to work from version to version.
+ *
+ * This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that
+ * what's being passed to it already is an OID and return that instead. A few examples.
+ *
+ * getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1'
+ * getOID('id-sha256') == '2.16.840.1.101.3.4.2.1'
+ * getOID('zzz') == 'zzz'
+ *
+ * @access public
+ * @return string
+ */
+ function getOID($name)
+ {
+ static $reverseMap;
+ if (!isset($reverseMap)) {
+ $reverseMap = array_flip($this->oids);
+ }
+ return isset($reverseMap[$name]) ? $reverseMap[$name] : $name;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP arbitrary precision integer arithmetic library.
+ *
+ * Supports base-2, base-10, base-16, and base-256 numbers. Uses the GMP or BCMath extensions, if available,
+ * and an internal implementation, otherwise.
+ *
+ * PHP version 5
+ *
+ * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
+ * {@link self::MODE_INTERNAL self::MODE_INTERNAL} mode)
+ *
+ * BigInteger uses base-2**26 to perform operations such as multiplication and division and
+ * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction. Because the largest possible
+ * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
+ * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
+ * used. As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %,
+ * which only supports integers. Although this fact will slow this library down, the fact that such a high
+ * base is being used should more than compensate.
+ *
+ * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie.
+ * (new \phpseclib\Math\BigInteger(pow(2, 26)))->value = array(0, 1)
+ *
+ * Useful resources are as follows:
+ *
+ * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}
+ * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}
+ * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip
+ *
+ * Here's an example of how to use this library:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger(2);
+ * $b = new \phpseclib\Math\BigInteger(3);
+ *
+ * $c = $a->add($b);
+ *
+ * echo $c->toString(); // outputs 5
+ * ?>
+ * </code>
+ *
+ * @category Math
+ * @package BigInteger
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2006 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ */
+
+namespace phpseclib\Math;
+
+use phpseclib\Crypt\Random;
+
+/**
+ * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
+ * numbers.
+ *
+ * @package BigInteger
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class BigInteger
+{
+ /**#@+
+ * Reduction constants
+ *
+ * @access private
+ * @see BigInteger::_reduce()
+ */
+ /**
+ * @see BigInteger::_montgomery()
+ * @see BigInteger::_prepMontgomery()
+ */
+ const MONTGOMERY = 0;
+ /**
+ * @see BigInteger::_barrett()
+ */
+ const BARRETT = 1;
+ /**
+ * @see BigInteger::_mod2()
+ */
+ const POWEROF2 = 2;
+ /**
+ * @see BigInteger::_remainder()
+ */
+ const CLASSIC = 3;
+ /**
+ * @see BigInteger::__clone()
+ */
+ const NONE = 4;
+ /**#@-*/
+
+ /**#@+
+ * Array constants
+ *
+ * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
+ * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
+ *
+ * @access private
+ */
+ /**
+ * $result[self::VALUE] contains the value.
+ */
+ const VALUE = 0;
+ /**
+ * $result[self::SIGN] contains the sign.
+ */
+ const SIGN = 1;
+ /**#@-*/
+
+ /**#@+
+ * @access private
+ * @see BigInteger::_montgomery()
+ * @see BigInteger::_barrett()
+ */
+ /**
+ * Cache constants
+ *
+ * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
+ */
+ const VARIABLE = 0;
+ /**
+ * $cache[self::DATA] contains the cached data.
+ */
+ const DATA = 1;
+ /**#@-*/
+
+ /**#@+
+ * Mode constants.
+ *
+ * @access private
+ * @see BigInteger::__construct()
+ */
+ /**
+ * To use the pure-PHP implementation
+ */
+ const MODE_INTERNAL = 1;
+ /**
+ * To use the BCMath library
+ *
+ * (if enabled; otherwise, the internal implementation will be used)
+ */
+ const MODE_BCMATH = 2;
+ /**
+ * To use the GMP library
+ *
+ * (if present; otherwise, either the BCMath or the internal implementation will be used)
+ */
+ const MODE_GMP = 3;
+ /**#@-*/
+
+ /**
+ * Karatsuba Cutoff
+ *
+ * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
+ *
+ * @access private
+ */
+ const KARATSUBA_CUTOFF = 25;
+
+ /**#@+
+ * Static properties used by the pure-PHP implementation.
+ *
+ * @see __construct()
+ */
+ protected static $base;
+ protected static $baseFull;
+ protected static $maxDigit;
+ protected static $msb;
+
+ /**
+ * $max10 in greatest $max10Len satisfying
+ * $max10 = 10**$max10Len <= 2**$base.
+ */
+ protected static $max10;
+
+ /**
+ * $max10Len in greatest $max10Len satisfying
+ * $max10 = 10**$max10Len <= 2**$base.
+ */
+ protected static $max10Len;
+ protected static $maxDigit2;
+ /**#@-*/
+
+ /**
+ * Holds the BigInteger's value.
+ *
+ * @var array
+ * @access private
+ */
+ var $value;
+
+ /**
+ * Holds the BigInteger's magnitude.
+ *
+ * @var bool
+ * @access private
+ */
+ var $is_negative = false;
+
+ /**
+ * Precision
+ *
+ * @see self::setPrecision()
+ * @access private
+ */
+ var $precision = -1;
+
+ /**
+ * Precision Bitmask
+ *
+ * @see self::setPrecision()
+ * @access private
+ */
+ var $bitmask = false;
+
+ /**
+ * Mode independent value used for serialization.
+ *
+ * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
+ * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
+ * however, $this->hex is only calculated when $this->__sleep() is called.
+ *
+ * @see self::__sleep()
+ * @see self::__wakeup()
+ * @var string
+ * @access private
+ */
+ var $hex;
+
+ /**
+ * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
+ *
+ * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
+ * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('0x32', 16); // 50 in base-16
+ *
+ * echo $a->toString(); // outputs 50
+ * ?>
+ * </code>
+ *
+ * @param $x base-10 number or base-$base number if $base set.
+ * @param int $base
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function __construct($x = 0, $base = 10)
+ {
+ if (!defined('MATH_BIGINTEGER_MODE')) {
+ switch (true) {
+ case extension_loaded('gmp'):
+ define('MATH_BIGINTEGER_MODE', self::MODE_GMP);
+ break;
+ case extension_loaded('bcmath'):
+ define('MATH_BIGINTEGER_MODE', self::MODE_BCMATH);
+ break;
+ default:
+ define('MATH_BIGINTEGER_MODE', self::MODE_INTERNAL);
+ }
+ }
+
+ if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
+ // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
+ $versions = array();
+
+ // avoid generating errors (even with suppression) when phpinfo() is disabled (common in production systems)
+ if (strpos(ini_get('disable_functions'), 'phpinfo') === false) {
+ ob_start();
+ @phpinfo();
+ $content = ob_get_contents();
+ ob_end_clean();
+
+ preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
+
+ if (!empty($matches[1])) {
+ for ($i = 0; $i < count($matches[1]); $i++) {
+ $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
+
+ // Remove letter part in OpenSSL version
+ if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
+ $versions[$matches[1][$i]] = $fullVersion;
+ } else {
+ $versions[$matches[1][$i]] = $m[0];
+ }
+ }
+ }
+ }
+
+ // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
+ switch (true) {
+ case !isset($versions['Header']):
+ case !isset($versions['Library']):
+ case $versions['Header'] == $versions['Library']:
+ case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
+ define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
+ break;
+ default:
+ define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
+ }
+ }
+
+ if (!defined('PHP_INT_SIZE')) {
+ define('PHP_INT_SIZE', 4);
+ }
+
+ if (empty(self::$base) && MATH_BIGINTEGER_MODE == self::MODE_INTERNAL) {
+ switch (PHP_INT_SIZE) {
+ case 8: // use 64-bit integers if int size is 8 bytes
+ self::$base = 31;
+ self::$baseFull = 0x80000000;
+ self::$maxDigit = 0x7FFFFFFF;
+ self::$msb = 0x40000000;
+ self::$max10 = 1000000000;
+ self::$max10Len = 9;
+ self::$maxDigit2 = pow(2, 62);
+ break;
+ //case 4: // use 64-bit floats if int size is 4 bytes
+ default:
+ self::$base = 26;
+ self::$baseFull = 0x4000000;
+ self::$maxDigit = 0x3FFFFFF;
+ self::$msb = 0x2000000;
+ self::$max10 = 10000000;
+ self::$max10Len = 7;
+ self::$maxDigit2 = pow(2, 52); // pow() prevents truncation
+ }
+ }
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ switch (true) {
+ case is_resource($x) && get_resource_type($x) == 'GMP integer':
+ // PHP 5.6 switched GMP from using resources to objects
+ case $x instanceof \GMP:
+ $this->value = $x;
+ return;
+ }
+ $this->value = gmp_init(0);
+ break;
+ case self::MODE_BCMATH:
+ $this->value = '0';
+ break;
+ default:
+ $this->value = array();
+ }
+
+ // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
+ // '0' is the only value like this per http://php.net/empty
+ if (empty($x) && (abs($base) != 256 || $x !== '0')) {
+ return;
+ }
+
+ switch ($base) {
+ case -256:
+ if (ord($x[0]) & 0x80) {
+ $x = ~$x;
+ $this->is_negative = true;
+ }
+ case 256:
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $this->value = function_exists('gmp_import') ?
+ gmp_import($x) :
+ gmp_init('0x' . bin2hex($x));
+ if ($this->is_negative) {
+ $this->value = gmp_neg($this->value);
+ }
+ break;
+ case self::MODE_BCMATH:
+ // round $len to the nearest 4 (thanks, DavidMJ!)
+ $len = (strlen($x) + 3) & 0xFFFFFFFC;
+
+ $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
+
+ for ($i = 0; $i < $len; $i+= 4) {
+ $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32
+ $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0);
+ }
+
+ if ($this->is_negative) {
+ $this->value = '-' . $this->value;
+ }
+
+ break;
+ // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
+ default:
+ while (strlen($x)) {
+ $this->value[] = $this->_bytes2int($this->_base256_rshift($x, self::$base));
+ }
+ }
+
+ if ($this->is_negative) {
+ if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
+ $this->is_negative = false;
+ }
+ $temp = $this->add(new static('-1'));
+ $this->value = $temp->value;
+ }
+ break;
+ case 16:
+ case -16:
+ if ($base > 0 && $x[0] == '-') {
+ $this->is_negative = true;
+ $x = substr($x, 1);
+ }
+
+ $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
+
+ $is_negative = false;
+ if ($base < 0 && hexdec($x[0]) >= 8) {
+ $this->is_negative = $is_negative = true;
+ $x = bin2hex(~pack('H*', $x));
+ }
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
+ $this->value = gmp_init($temp);
+ $this->is_negative = false;
+ break;
+ case self::MODE_BCMATH:
+ $x = (strlen($x) & 1) ? '0' . $x : $x;
+ $temp = new static(pack('H*', $x), 256);
+ $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
+ $this->is_negative = false;
+ break;
+ default:
+ $x = (strlen($x) & 1) ? '0' . $x : $x;
+ $temp = new static(pack('H*', $x), 256);
+ $this->value = $temp->value;
+ }
+
+ if ($is_negative) {
+ $temp = $this->add(new static('-1'));
+ $this->value = $temp->value;
+ }
+ break;
+ case 10:
+ case -10:
+ // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
+ // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
+ // [^-0-9].*: find any non-numeric characters and then any characters that follow that
+ $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
+ if (!strlen($x) || $x == '-') {
+ $x = '0';
+ }
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $this->value = gmp_init($x);
+ break;
+ case self::MODE_BCMATH:
+ // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
+ // results then doing it on '-1' does (modInverse does $x[0])
+ $this->value = $x === '-' ? '0' : (string) $x;
+ break;
+ default:
+ $temp = new static();
+
+ $multiplier = new static();
+ $multiplier->value = array(self::$max10);
+
+ if ($x[0] == '-') {
+ $this->is_negative = true;
+ $x = substr($x, 1);
+ }
+
+ $x = str_pad($x, strlen($x) + ((self::$max10Len - 1) * strlen($x)) % self::$max10Len, 0, STR_PAD_LEFT);
+ while (strlen($x)) {
+ $temp = $temp->multiply($multiplier);
+ $temp = $temp->add(new static($this->_int2bytes(substr($x, 0, self::$max10Len)), 256));
+ $x = substr($x, self::$max10Len);
+ }
+
+ $this->value = $temp->value;
+ }
+ break;
+ case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
+ case -2:
+ if ($base > 0 && $x[0] == '-') {
+ $this->is_negative = true;
+ $x = substr($x, 1);
+ }
+
+ $x = preg_replace('#^([01]*).*#', '$1', $x);
+ $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
+
+ $str = '0x';
+ while (strlen($x)) {
+ $part = substr($x, 0, 4);
+ $str.= dechex(bindec($part));
+ $x = substr($x, 4);
+ }
+
+ if ($this->is_negative) {
+ $str = '-' . $str;
+ }
+
+ $temp = new static($str, 8 * $base); // ie. either -16 or +16
+ $this->value = $temp->value;
+ $this->is_negative = $temp->is_negative;
+
+ break;
+ default:
+ // base not supported, so we'll let $this == 0
+ }
+ }
+
+ /**
+ * Converts a BigInteger to a byte string (eg. base-256).
+ *
+ * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
+ * saved as two's compliment.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('65');
+ *
+ * echo $a->toBytes(); // outputs chr(65)
+ * ?>
+ * </code>
+ *
+ * @param bool $twos_compliment
+ * @return string
+ * @access public
+ * @internal Converts a base-2**26 number to base-2**8
+ */
+ function toBytes($twos_compliment = false)
+ {
+ if ($twos_compliment) {
+ $comparison = $this->compare(new static());
+ if ($comparison == 0) {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+
+ $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy();
+ $bytes = $temp->toBytes();
+
+ if (!strlen($bytes)) { // eg. if the number we're trying to convert is -1
+ $bytes = chr(0);
+ }
+
+ if (ord($bytes[0]) & 0x80) {
+ $bytes = chr(0) . $bytes;
+ }
+
+ return $comparison < 0 ? ~$bytes : $bytes;
+ }
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ if (gmp_cmp($this->value, gmp_init(0)) == 0) {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+
+ if (function_exists('gmp_export')) {
+ $temp = gmp_export($this->value);
+ } else {
+ $temp = gmp_strval(gmp_abs($this->value), 16);
+ $temp = (strlen($temp) & 1) ? '0' . $temp : $temp;
+ $temp = pack('H*', $temp);
+ }
+
+ return $this->precision > 0 ?
+ substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
+ ltrim($temp, chr(0));
+ case self::MODE_BCMATH:
+ if ($this->value === '0') {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+
+ $value = '';
+ $current = $this->value;
+
+ if ($current[0] == '-') {
+ $current = substr($current, 1);
+ }
+
+ while (bccomp($current, '0', 0) > 0) {
+ $temp = bcmod($current, '16777216');
+ $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
+ $current = bcdiv($current, '16777216', 0);
+ }
+
+ return $this->precision > 0 ?
+ substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
+ ltrim($value, chr(0));
+ }
+
+ if (!count($this->value)) {
+ return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
+ }
+ $result = $this->_int2bytes($this->value[count($this->value) - 1]);
+
+ $temp = $this->copy();
+
+ for ($i = count($temp->value) - 2; $i >= 0; --$i) {
+ $temp->_base256_lshift($result, self::$base);
+ $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
+ }
+
+ return $this->precision > 0 ?
+ str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) :
+ $result;
+ }
+
+ /**
+ * Converts a BigInteger to a hex string (eg. base-16)).
+ *
+ * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
+ * saved as two's compliment.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('65');
+ *
+ * echo $a->toHex(); // outputs '41'
+ * ?>
+ * </code>
+ *
+ * @param bool $twos_compliment
+ * @return string
+ * @access public
+ * @internal Converts a base-2**26 number to base-2**8
+ */
+ function toHex($twos_compliment = false)
+ {
+ return bin2hex($this->toBytes($twos_compliment));
+ }
+
+ /**
+ * Converts a BigInteger to a bit string (eg. base-2).
+ *
+ * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
+ * saved as two's compliment.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('65');
+ *
+ * echo $a->toBits(); // outputs '1000001'
+ * ?>
+ * </code>
+ *
+ * @param bool $twos_compliment
+ * @return string
+ * @access public
+ * @internal Converts a base-2**26 number to base-2**2
+ */
+ function toBits($twos_compliment = false)
+ {
+ $hex = $this->toHex($twos_compliment);
+ $bits = '';
+ for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
+ $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
+ }
+ if ($start) { // hexdec('') == 0
+ $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
+ }
+ $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
+
+ if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
+ return '0' . $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Converts a BigInteger to a base-10 number.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('50');
+ *
+ * echo $a->toString(); // outputs 50
+ * ?>
+ * </code>
+ *
+ * @return string
+ * @access public
+ * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
+ */
+ function toString()
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ return gmp_strval($this->value);
+ case self::MODE_BCMATH:
+ if ($this->value === '0') {
+ return '0';
+ }
+
+ return ltrim($this->value, '0');
+ }
+
+ if (!count($this->value)) {
+ return '0';
+ }
+
+ $temp = $this->copy();
+ $temp->is_negative = false;
+
+ $divisor = new static();
+ $divisor->value = array(self::$max10);
+ $result = '';
+ while (count($temp->value)) {
+ list($temp, $mod) = $temp->divide($divisor);
+ $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', self::$max10Len, '0', STR_PAD_LEFT) . $result;
+ }
+ $result = ltrim($result, '0');
+ if (empty($result)) {
+ $result = '0';
+ }
+
+ if ($this->is_negative) {
+ $result = '-' . $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Copy an object
+ *
+ * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee
+ * that all objects are passed by value, when appropriate. More information can be found here:
+ *
+ * {@link http://php.net/language.oop5.basic#51624}
+ *
+ * @access public
+ * @see self::__clone()
+ * @return \phpseclib\Math\BigInteger
+ */
+ function copy()
+ {
+ $temp = new static();
+ $temp->value = $this->value;
+ $temp->is_negative = $this->is_negative;
+ $temp->precision = $this->precision;
+ $temp->bitmask = $this->bitmask;
+ return $temp;
+ }
+
+ /**
+ * __toString() magic method
+ *
+ * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
+ * toString().
+ *
+ * @access public
+ * @internal Implemented per a suggestion by Techie-Michael - thanks!
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * __clone() magic method
+ *
+ * Although you can call BigInteger::__toString() directly in PHP5, you cannot call BigInteger::__clone() directly
+ * in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5
+ * only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and
+ * PHP5, call BigInteger::copy(), instead.
+ *
+ * @access public
+ * @see self::copy()
+ * @return \phpseclib\Math\BigInteger
+ */
+ function __clone()
+ {
+ return $this->copy();
+ }
+
+ /**
+ * __sleep() magic method
+ *
+ * Will be called, automatically, when serialize() is called on a BigInteger object.
+ *
+ * @see self::__wakeup()
+ * @access public
+ */
+ function __sleep()
+ {
+ $this->hex = $this->toHex(true);
+ $vars = array('hex');
+ if ($this->precision > 0) {
+ $vars[] = 'precision';
+ }
+ return $vars;
+ }
+
+ /**
+ * __wakeup() magic method
+ *
+ * Will be called, automatically, when unserialize() is called on a BigInteger object.
+ *
+ * @see self::__sleep()
+ * @access public
+ */
+ function __wakeup()
+ {
+ $temp = new static($this->hex, -16);
+ $this->value = $temp->value;
+ $this->is_negative = $temp->is_negative;
+ if ($this->precision > 0) {
+ // recalculate $this->bitmask
+ $this->setPrecision($this->precision);
+ }
+ }
+
+ /**
+ * __debugInfo() magic method
+ *
+ * Will be called, automatically, when print_r() or var_dump() are called
+ *
+ * @access public
+ */
+ function __debugInfo()
+ {
+ $opts = array();
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $engine = 'gmp';
+ break;
+ case self::MODE_BCMATH:
+ $engine = 'bcmath';
+ break;
+ case self::MODE_INTERNAL:
+ $engine = 'internal';
+ $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit';
+ }
+ if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
+ $opts[] = 'OpenSSL';
+ }
+ if (!empty($opts)) {
+ $engine.= ' (' . implode($opts, ', ') . ')';
+ }
+ return array(
+ 'value' => '0x' . $this->toHex(true),
+ 'engine' => $engine
+ );
+ }
+
+ /**
+ * Adds two BigIntegers.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('10');
+ * $b = new \phpseclib\Math\BigInteger('20');
+ *
+ * $c = $a->add($b);
+ *
+ * echo $c->toString(); // outputs 30
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $y
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal Performs base-2**52 addition
+ */
+ function add($y)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_add($this->value, $y->value);
+
+ return $this->_normalize($temp);
+ case self::MODE_BCMATH:
+ $temp = new static();
+ $temp->value = bcadd($this->value, $y->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative);
+
+ $result = new static();
+ $result->value = $temp[self::VALUE];
+ $result->is_negative = $temp[self::SIGN];
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Performs addition.
+ *
+ * @param array $x_value
+ * @param bool $x_negative
+ * @param array $y_value
+ * @param bool $y_negative
+ * @return array
+ * @access private
+ */
+ function _add($x_value, $x_negative, $y_value, $y_negative)
+ {
+ $x_size = count($x_value);
+ $y_size = count($y_value);
+
+ if ($x_size == 0) {
+ return array(
+ self::VALUE => $y_value,
+ self::SIGN => $y_negative
+ );
+ } elseif ($y_size == 0) {
+ return array(
+ self::VALUE => $x_value,
+ self::SIGN => $x_negative
+ );
+ }
+
+ // subtract, if appropriate
+ if ($x_negative != $y_negative) {
+ if ($x_value == $y_value) {
+ return array(
+ self::VALUE => array(),
+ self::SIGN => false
+ );
+ }
+
+ $temp = $this->_subtract($x_value, false, $y_value, false);
+ $temp[self::SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
+ $x_negative : $y_negative;
+
+ return $temp;
+ }
+
+ if ($x_size < $y_size) {
+ $size = $x_size;
+ $value = $y_value;
+ } else {
+ $size = $y_size;
+ $value = $x_value;
+ }
+
+ $value[count($value)] = 0; // just in case the carry adds an extra digit
+
+ $carry = 0;
+ for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
+ $sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry;
+ $carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
+ $sum = $carry ? $sum - self::$maxDigit2 : $sum;
+
+ $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
+
+ $value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
+ $value[$j] = $temp;
+ }
+
+ if ($j == $size) { // ie. if $y_size is odd
+ $sum = $x_value[$i] + $y_value[$i] + $carry;
+ $carry = $sum >= self::$baseFull;
+ $value[$i] = $carry ? $sum - self::$baseFull : $sum;
+ ++$i; // ie. let $i = $j since we've just done $value[$i]
+ }
+
+ if ($carry) {
+ for (; $value[$i] == self::$maxDigit; ++$i) {
+ $value[$i] = 0;
+ }
+ ++$value[$i];
+ }
+
+ return array(
+ self::VALUE => $this->_trim($value),
+ self::SIGN => $x_negative
+ );
+ }
+
+ /**
+ * Subtracts two BigIntegers.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('10');
+ * $b = new \phpseclib\Math\BigInteger('20');
+ *
+ * $c = $a->subtract($b);
+ *
+ * echo $c->toString(); // outputs -10
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $y
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal Performs base-2**52 subtraction
+ */
+ function subtract($y)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_sub($this->value, $y->value);
+
+ return $this->_normalize($temp);
+ case self::MODE_BCMATH:
+ $temp = new static();
+ $temp->value = bcsub($this->value, $y->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
+
+ $result = new static();
+ $result->value = $temp[self::VALUE];
+ $result->is_negative = $temp[self::SIGN];
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Performs subtraction.
+ *
+ * @param array $x_value
+ * @param bool $x_negative
+ * @param array $y_value
+ * @param bool $y_negative
+ * @return array
+ * @access private
+ */
+ function _subtract($x_value, $x_negative, $y_value, $y_negative)
+ {
+ $x_size = count($x_value);
+ $y_size = count($y_value);
+
+ if ($x_size == 0) {
+ return array(
+ self::VALUE => $y_value,
+ self::SIGN => !$y_negative
+ );
+ } elseif ($y_size == 0) {
+ return array(
+ self::VALUE => $x_value,
+ self::SIGN => $x_negative
+ );
+ }
+
+ // add, if appropriate (ie. -$x - +$y or +$x - -$y)
+ if ($x_negative != $y_negative) {
+ $temp = $this->_add($x_value, false, $y_value, false);
+ $temp[self::SIGN] = $x_negative;
+
+ return $temp;
+ }
+
+ $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
+
+ if (!$diff) {
+ return array(
+ self::VALUE => array(),
+ self::SIGN => false
+ );
+ }
+
+ // switch $x and $y around, if appropriate.
+ if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
+ $temp = $x_value;
+ $x_value = $y_value;
+ $y_value = $temp;
+
+ $x_negative = !$x_negative;
+
+ $x_size = count($x_value);
+ $y_size = count($y_value);
+ }
+
+ // at this point, $x_value should be at least as big as - if not bigger than - $y_value
+
+ $carry = 0;
+ for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
+ $sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry;
+ $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
+ $sum = $carry ? $sum + self::$maxDigit2 : $sum;
+
+ $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
+
+ $x_value[$i] = (int) ($sum - self::$baseFull * $temp);
+ $x_value[$j] = $temp;
+ }
+
+ if ($j == $y_size) { // ie. if $y_size is odd
+ $sum = $x_value[$i] - $y_value[$i] - $carry;
+ $carry = $sum < 0;
+ $x_value[$i] = $carry ? $sum + self::$baseFull : $sum;
+ ++$i;
+ }
+
+ if ($carry) {
+ for (; !$x_value[$i]; ++$i) {
+ $x_value[$i] = self::$maxDigit;
+ }
+ --$x_value[$i];
+ }
+
+ return array(
+ self::VALUE => $this->_trim($x_value),
+ self::SIGN => $x_negative
+ );
+ }
+
+ /**
+ * Multiplies two BigIntegers
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('10');
+ * $b = new \phpseclib\Math\BigInteger('20');
+ *
+ * $c = $a->multiply($b);
+ *
+ * echo $c->toString(); // outputs 200
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $x
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function multiply($x)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_mul($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case self::MODE_BCMATH:
+ $temp = new static();
+ $temp->value = bcmul($this->value, $x->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
+
+ $product = new static();
+ $product->value = $temp[self::VALUE];
+ $product->is_negative = $temp[self::SIGN];
+
+ return $this->_normalize($product);
+ }
+
+ /**
+ * Performs multiplication.
+ *
+ * @param array $x_value
+ * @param bool $x_negative
+ * @param array $y_value
+ * @param bool $y_negative
+ * @return array
+ * @access private
+ */
+ function _multiply($x_value, $x_negative, $y_value, $y_negative)
+ {
+ //if ( $x_value == $y_value ) {
+ // return array(
+ // self::VALUE => $this->_square($x_value),
+ // self::SIGN => $x_sign != $y_value
+ // );
+ //}
+
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+
+ if (!$x_length || !$y_length) { // a 0 is being multiplied
+ return array(
+ self::VALUE => array(),
+ self::SIGN => false
+ );
+ }
+
+ return array(
+ self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ?
+ $this->_trim($this->_regularMultiply($x_value, $y_value)) :
+ $this->_trim($this->_karatsuba($x_value, $y_value)),
+ self::SIGN => $x_negative != $y_negative
+ );
+ }
+
+ /**
+ * Performs long multiplication on two BigIntegers
+ *
+ * Modeled after 'multiply' in MutableBigInteger.java.
+ *
+ * @param array $x_value
+ * @param array $y_value
+ * @return array
+ * @access private
+ */
+ function _regularMultiply($x_value, $y_value)
+ {
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+
+ if (!$x_length || !$y_length) { // a 0 is being multiplied
+ return array();
+ }
+
+ if ($x_length < $y_length) {
+ $temp = $x_value;
+ $x_value = $y_value;
+ $y_value = $temp;
+
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+ }
+
+ $product_value = $this->_array_repeat(0, $x_length + $y_length);
+
+ // the following for loop could be removed if the for loop following it
+ // (the one with nested for loops) initially set $i to 0, but
+ // doing so would also make the result in one set of unnecessary adds,
+ // since on the outermost loops first pass, $product->value[$k] is going
+ // to always be 0
+
+ $carry = 0;
+
+ for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
+ $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
+ }
+
+ $product_value[$j] = $carry;
+
+ // the above for loop is what the previous comment was talking about. the
+ // following for loop is the "one with nested for loops"
+ for ($i = 1; $i < $y_length; ++$i) {
+ $carry = 0;
+
+ for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
+ $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
+ }
+
+ $product_value[$k] = $carry;
+ }
+
+ return $product_value;
+ }
+
+ /**
+ * Performs Karatsuba multiplication on two BigIntegers
+ *
+ * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
+ *
+ * @param array $x_value
+ * @param array $y_value
+ * @return array
+ * @access private
+ */
+ function _karatsuba($x_value, $y_value)
+ {
+ $m = min(count($x_value) >> 1, count($y_value) >> 1);
+
+ if ($m < self::KARATSUBA_CUTOFF) {
+ return $this->_regularMultiply($x_value, $y_value);
+ }
+
+ $x1 = array_slice($x_value, $m);
+ $x0 = array_slice($x_value, 0, $m);
+ $y1 = array_slice($y_value, $m);
+ $y0 = array_slice($y_value, 0, $m);
+
+ $z2 = $this->_karatsuba($x1, $y1);
+ $z0 = $this->_karatsuba($x0, $y0);
+
+ $z1 = $this->_add($x1, false, $x0, false);
+ $temp = $this->_add($y1, false, $y0, false);
+ $z1 = $this->_karatsuba($z1[self::VALUE], $temp[self::VALUE]);
+ $temp = $this->_add($z2, false, $z0, false);
+ $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false);
+
+ $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
+ $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
+
+ $xy = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
+ $xy = $this->_add($xy[self::VALUE], $xy[self::SIGN], $z0, false);
+
+ return $xy[self::VALUE];
+ }
+
+ /**
+ * Performs squaring
+ *
+ * @param array $x
+ * @return array
+ * @access private
+ */
+ function _square($x = false)
+ {
+ return count($x) < 2 * self::KARATSUBA_CUTOFF ?
+ $this->_trim($this->_baseSquare($x)) :
+ $this->_trim($this->_karatsubaSquare($x));
+ }
+
+ /**
+ * Performs traditional squaring on two BigIntegers
+ *
+ * Squaring can be done faster than multiplying a number by itself can be. See
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
+ *
+ * @param array $value
+ * @return array
+ * @access private
+ */
+ function _baseSquare($value)
+ {
+ if (empty($value)) {
+ return array();
+ }
+ $square_value = $this->_array_repeat(0, 2 * count($value));
+
+ for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
+ $i2 = $i << 1;
+
+ $temp = $square_value[$i2] + $value[$i] * $value[$i];
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $square_value[$i2] = (int) ($temp - self::$baseFull * $carry);
+
+ // note how we start from $i+1 instead of 0 as we do in multiplication.
+ for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
+ $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $square_value[$k] = (int) ($temp - self::$baseFull * $carry);
+ }
+
+ // the following line can yield values larger 2**15. at this point, PHP should switch
+ // over to floats.
+ $square_value[$i + $max_index + 1] = $carry;
+ }
+
+ return $square_value;
+ }
+
+ /**
+ * Performs Karatsuba "squaring" on two BigIntegers
+ *
+ * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
+ *
+ * @param array $value
+ * @return array
+ * @access private
+ */
+ function _karatsubaSquare($value)
+ {
+ $m = count($value) >> 1;
+
+ if ($m < self::KARATSUBA_CUTOFF) {
+ return $this->_baseSquare($value);
+ }
+
+ $x1 = array_slice($value, $m);
+ $x0 = array_slice($value, 0, $m);
+
+ $z2 = $this->_karatsubaSquare($x1);
+ $z0 = $this->_karatsubaSquare($x0);
+
+ $z1 = $this->_add($x1, false, $x0, false);
+ $z1 = $this->_karatsubaSquare($z1[self::VALUE]);
+ $temp = $this->_add($z2, false, $z0, false);
+ $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false);
+
+ $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
+ $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
+
+ $xx = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
+ $xx = $this->_add($xx[self::VALUE], $xx[self::SIGN], $z0, false);
+
+ return $xx[self::VALUE];
+ }
+
+ /**
+ * Divides two BigIntegers.
+ *
+ * Returns an array whose first element contains the quotient and whose second element contains the
+ * "common residue". If the remainder would be positive, the "common residue" and the remainder are the
+ * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
+ * and the divisor (basically, the "common residue" is the first positive modulo).
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('10');
+ * $b = new \phpseclib\Math\BigInteger('20');
+ *
+ * list($quotient, $remainder) = $a->divide($b);
+ *
+ * echo $quotient->toString(); // outputs 0
+ * echo "\r\n";
+ * echo $remainder->toString(); // outputs 10
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $y
+ * @return array
+ * @access public
+ * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
+ */
+ function divide($y)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $quotient = new static();
+ $remainder = new static();
+
+ list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
+
+ if (gmp_sign($remainder->value) < 0) {
+ $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
+ }
+
+ return array($this->_normalize($quotient), $this->_normalize($remainder));
+ case self::MODE_BCMATH:
+ $quotient = new static();
+ $remainder = new static();
+
+ $quotient->value = bcdiv($this->value, $y->value, 0);
+ $remainder->value = bcmod($this->value, $y->value);
+
+ if ($remainder->value[0] == '-') {
+ $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0);
+ }
+
+ return array($this->_normalize($quotient), $this->_normalize($remainder));
+ }
+
+ if (count($y->value) == 1) {
+ list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
+ $quotient = new static();
+ $remainder = new static();
+ $quotient->value = $q;
+ $remainder->value = array($r);
+ $quotient->is_negative = $this->is_negative != $y->is_negative;
+ return array($this->_normalize($quotient), $this->_normalize($remainder));
+ }
+
+ static $zero;
+ if (!isset($zero)) {
+ $zero = new static();
+ }
+
+ $x = $this->copy();
+ $y = $y->copy();
+
+ $x_sign = $x->is_negative;
+ $y_sign = $y->is_negative;
+
+ $x->is_negative = $y->is_negative = false;
+
+ $diff = $x->compare($y);
+
+ if (!$diff) {
+ $temp = new static();
+ $temp->value = array(1);
+ $temp->is_negative = $x_sign != $y_sign;
+ return array($this->_normalize($temp), $this->_normalize(new static()));
+ }
+
+ if ($diff < 0) {
+ // if $x is negative, "add" $y.
+ if ($x_sign) {
+ $x = $y->subtract($x);
+ }
+ return array($this->_normalize(new static()), $this->_normalize($x));
+ }
+
+ // normalize $x and $y as described in HAC 14.23 / 14.24
+ $msb = $y->value[count($y->value) - 1];
+ for ($shift = 0; !($msb & self::$msb); ++$shift) {
+ $msb <<= 1;
+ }
+ $x->_lshift($shift);
+ $y->_lshift($shift);
+ $y_value = &$y->value;
+
+ $x_max = count($x->value) - 1;
+ $y_max = count($y->value) - 1;
+
+ $quotient = new static();
+ $quotient_value = &$quotient->value;
+ $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
+
+ static $temp, $lhs, $rhs;
+ if (!isset($temp)) {
+ $temp = new static();
+ $lhs = new static();
+ $rhs = new static();
+ }
+ $temp_value = &$temp->value;
+ $rhs_value = &$rhs->value;
+
+ // $temp = $y << ($x_max - $y_max-1) in base 2**26
+ $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
+
+ while ($x->compare($temp) >= 0) {
+ // calculate the "common residue"
+ ++$quotient_value[$x_max - $y_max];
+ $x = $x->subtract($temp);
+ $x_max = count($x->value) - 1;
+ }
+
+ for ($i = $x_max; $i >= $y_max + 1; --$i) {
+ $x_value = &$x->value;
+ $x_window = array(
+ isset($x_value[$i]) ? $x_value[$i] : 0,
+ isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0,
+ isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0
+ );
+ $y_window = array(
+ $y_value[$y_max],
+ ($y_max > 0) ? $y_value[$y_max - 1] : 0
+ );
+
+ $q_index = $i - $y_max - 1;
+ if ($x_window[0] == $y_window[0]) {
+ $quotient_value[$q_index] = self::$maxDigit;
+ } else {
+ $quotient_value[$q_index] = $this->_safe_divide(
+ $x_window[0] * self::$baseFull + $x_window[1],
+ $y_window[0]
+ );
+ }
+
+ $temp_value = array($y_window[1], $y_window[0]);
+
+ $lhs->value = array($quotient_value[$q_index]);
+ $lhs = $lhs->multiply($temp);
+
+ $rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
+
+ while ($lhs->compare($rhs) > 0) {
+ --$quotient_value[$q_index];
+
+ $lhs->value = array($quotient_value[$q_index]);
+ $lhs = $lhs->multiply($temp);
+ }
+
+ $adjust = $this->_array_repeat(0, $q_index);
+ $temp_value = array($quotient_value[$q_index]);
+ $temp = $temp->multiply($y);
+ $temp_value = &$temp->value;
+ if ($temp_value !== []) {
+ $temp_value = array_merge($adjust, $temp_value);
+ }
+
+ $x = $x->subtract($temp);
+
+ if ($x->compare($zero) < 0) {
+ $temp_value = array_merge($adjust, $y_value);
+ $x = $x->add($temp);
+
+ --$quotient_value[$q_index];
+ }
+
+ $x_max = count($x_value) - 1;
+ }
+
+ // unnormalize the remainder
+ $x->_rshift($shift);
+
+ $quotient->is_negative = $x_sign != $y_sign;
+
+ // calculate the "common residue", if appropriate
+ if ($x_sign) {
+ $y->_rshift($shift);
+ $x = $y->subtract($x);
+ }
+
+ return array($this->_normalize($quotient), $this->_normalize($x));
+ }
+
+ /**
+ * Divides a BigInteger by a regular integer
+ *
+ * abc / x = a00 / x + b0 / x + c / x
+ *
+ * @param array $dividend
+ * @param array $divisor
+ * @return array
+ * @access private
+ */
+ function _divide_digit($dividend, $divisor)
+ {
+ $carry = 0;
+ $result = array();
+
+ for ($i = count($dividend) - 1; $i >= 0; --$i) {
+ $temp = self::$baseFull * $carry + $dividend[$i];
+ $result[$i] = $this->_safe_divide($temp, $divisor);
+ $carry = (int) ($temp - $divisor * $result[$i]);
+ }
+
+ return array($result, $carry);
+ }
+
+ /**
+ * Performs modular exponentiation.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger('10');
+ * $b = new \phpseclib\Math\BigInteger('20');
+ * $c = new \phpseclib\Math\BigInteger('30');
+ *
+ * $c = $a->modPow($b, $c);
+ *
+ * echo $c->toString(); // outputs 10
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $e
+ * @param \phpseclib\Math\BigInteger $n
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
+ * and although the approach involving repeated squaring does vastly better, it, too, is impractical
+ * for our purposes. The reason being that division - by far the most complicated and time-consuming
+ * of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
+ *
+ * Modular reductions resolve this issue. Although an individual modular reduction takes more time
+ * then an individual division, when performed in succession (with the same modulo), they're a lot faster.
+ *
+ * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction,
+ * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the
+ * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
+ * the product of two odd numbers is odd), but what about when RSA isn't used?
+ *
+ * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a
+ * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the
+ * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however,
+ * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
+ * the other, a power of two - and recombine them, later. This is the method that this modPow function uses.
+ * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
+ */
+ function modPow($e, $n)
+ {
+ $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
+
+ if ($e->compare(new static()) < 0) {
+ $e = $e->abs();
+
+ $temp = $this->modInverse($n);
+ if ($temp === false) {
+ return false;
+ }
+
+ return $this->_normalize($temp->modPow($e, $n));
+ }
+
+ if (MATH_BIGINTEGER_MODE == self::MODE_GMP) {
+ $temp = new static();
+ $temp->value = gmp_powm($this->value, $e->value, $n->value);
+
+ return $this->_normalize($temp);
+ }
+
+ if ($this->compare(new static()) < 0 || $this->compare($n) > 0) {
+ list(, $temp) = $this->divide($n);
+ return $temp->modPow($e, $n);
+ }
+
+ if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
+ $components = array(
+ 'modulus' => $n->toBytes(true),
+ 'publicExponent' => $e->toBytes(true)
+ );
+
+ $components = array(
+ 'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']),
+ 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
+ );
+
+ $RSAPublicKey = pack(
+ 'Ca*a*a*',
+ 48,
+ $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
+ $components['modulus'],
+ $components['publicExponent']
+ );
+
+ $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
+ $RSAPublicKey = chr(0) . $RSAPublicKey;
+ $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
+
+ $encapsulated = pack(
+ 'Ca*a*',
+ 48,
+ $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)),
+ $rsaOID . $RSAPublicKey
+ );
+
+ $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
+ chunk_split(base64_encode($encapsulated)) .
+ '-----END PUBLIC KEY-----';
+
+ $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT);
+
+ if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
+ return new static($result, 256);
+ }
+ }
+
+ if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
+ $temp = new static();
+ $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
+
+ return $this->_normalize($temp);
+ }
+
+ if (empty($e->value)) {
+ $temp = new static();
+ $temp->value = array(1);
+ return $this->_normalize($temp);
+ }
+
+ if ($e->value == array(1)) {
+ list(, $temp) = $this->divide($n);
+ return $this->_normalize($temp);
+ }
+
+ if ($e->value == array(2)) {
+ $temp = new static();
+ $temp->value = $this->_square($this->value);
+ list(, $temp) = $temp->divide($n);
+ return $this->_normalize($temp);
+ }
+
+ return $this->_normalize($this->_slidingWindow($e, $n, self::BARRETT));
+
+ // the following code, although not callable, can be run independently of the above code
+ // although the above code performed better in my benchmarks the following could might
+ // perform better under different circumstances. in lieu of deleting it it's just been
+ // made uncallable
+
+ // is the modulo odd?
+ if ($n->value[0] & 1) {
+ return $this->_normalize($this->_slidingWindow($e, $n, self::MONTGOMERY));
+ }
+ // if it's not, it's even
+
+ // find the lowest set bit (eg. the max pow of 2 that divides $n)
+ for ($i = 0; $i < count($n->value); ++$i) {
+ if ($n->value[$i]) {
+ $temp = decbin($n->value[$i]);
+ $j = strlen($temp) - strrpos($temp, '1') - 1;
+ $j+= 26 * $i;
+ break;
+ }
+ }
+ // at this point, 2^$j * $n/(2^$j) == $n
+
+ $mod1 = $n->copy();
+ $mod1->_rshift($j);
+ $mod2 = new static();
+ $mod2->value = array(1);
+ $mod2->_lshift($j);
+
+ $part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static();
+ $part2 = $this->_slidingWindow($e, $mod2, self::POWEROF2);
+
+ $y1 = $mod2->modInverse($mod1);
+ $y2 = $mod1->modInverse($mod2);
+
+ $result = $part1->multiply($mod2);
+ $result = $result->multiply($y1);
+
+ $temp = $part2->multiply($mod1);
+ $temp = $temp->multiply($y2);
+
+ $result = $result->add($temp);
+ list(, $result) = $result->divide($n);
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Performs modular exponentiation.
+ *
+ * Alias for modPow().
+ *
+ * @param \phpseclib\Math\BigInteger $e
+ * @param \phpseclib\Math\BigInteger $n
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function powMod($e, $n)
+ {
+ return $this->modPow($e, $n);
+ }
+
+ /**
+ * Sliding Window k-ary Modular Exponentiation
+ *
+ * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims,
+ * however, this function performs a modular reduction after every multiplication and squaring operation.
+ * As such, this function has the same preconditions that the reductions being used do.
+ *
+ * @param \phpseclib\Math\BigInteger $e
+ * @param \phpseclib\Math\BigInteger $n
+ * @param int $mode
+ * @return \phpseclib\Math\BigInteger
+ * @access private
+ */
+ function _slidingWindow($e, $n, $mode)
+ {
+ static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function
+ //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
+
+ $e_value = $e->value;
+ $e_length = count($e_value) - 1;
+ $e_bits = decbin($e_value[$e_length]);
+ for ($i = $e_length - 1; $i >= 0; --$i) {
+ $e_bits.= str_pad(decbin($e_value[$i]), self::$base, '0', STR_PAD_LEFT);
+ }
+
+ $e_length = strlen($e_bits);
+
+ // calculate the appropriate window size.
+ // $window_size == 3 if $window_ranges is between 25 and 81, for example.
+ for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) {
+ }
+
+ $n_value = $n->value;
+
+ // precompute $this^0 through $this^$window_size
+ $powers = array();
+ $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode);
+ $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode);
+
+ // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
+ // in a 1. ie. it's supposed to be odd.
+ $temp = 1 << ($window_size - 1);
+ for ($i = 1; $i < $temp; ++$i) {
+ $i2 = $i << 1;
+ $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode);
+ }
+
+ $result = array(1);
+ $result = $this->_prepareReduce($result, $n_value, $mode);
+
+ for ($i = 0; $i < $e_length;) {
+ if (!$e_bits[$i]) {
+ $result = $this->_squareReduce($result, $n_value, $mode);
+ ++$i;
+ } else {
+ for ($j = $window_size - 1; $j > 0; --$j) {
+ if (!empty($e_bits[$i + $j])) {
+ break;
+ }
+ }
+
+ // eg. the length of substr($e_bits, $i, $j + 1)
+ for ($k = 0; $k <= $j; ++$k) {
+ $result = $this->_squareReduce($result, $n_value, $mode);
+ }
+
+ $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
+
+ $i += $j + 1;
+ }
+ }
+
+ $temp = new static();
+ $temp->value = $this->_reduce($result, $n_value, $mode);
+
+ return $temp;
+ }
+
+ /**
+ * Modular reduction
+ *
+ * For most $modes this will return the remainder.
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $n
+ * @param int $mode
+ * @return array
+ */
+ function _reduce($x, $n, $mode)
+ {
+ switch ($mode) {
+ case self::MONTGOMERY:
+ return $this->_montgomery($x, $n);
+ case self::BARRETT:
+ return $this->_barrett($x, $n);
+ case self::POWEROF2:
+ $lhs = new static();
+ $lhs->value = $x;
+ $rhs = new static();
+ $rhs->value = $n;
+ return $x->_mod2($n);
+ case self::CLASSIC:
+ $lhs = new static();
+ $lhs->value = $x;
+ $rhs = new static();
+ $rhs->value = $n;
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ case self::NONE:
+ return $x;
+ default:
+ // an invalid $mode was provided
+ }
+ }
+
+ /**
+ * Modular reduction preperation
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $n
+ * @param int $mode
+ * @return array
+ */
+ function _prepareReduce($x, $n, $mode)
+ {
+ if ($mode == self::MONTGOMERY) {
+ return $this->_prepMontgomery($x, $n);
+ }
+ return $this->_reduce($x, $n, $mode);
+ }
+
+ /**
+ * Modular multiply
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $y
+ * @param array $n
+ * @param int $mode
+ * @return array
+ */
+ function _multiplyReduce($x, $y, $n, $mode)
+ {
+ if ($mode == self::MONTGOMERY) {
+ return $this->_montgomeryMultiply($x, $y, $n);
+ }
+ $temp = $this->_multiply($x, false, $y, false);
+ return $this->_reduce($temp[self::VALUE], $n, $mode);
+ }
+
+ /**
+ * Modular square
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $n
+ * @param int $mode
+ * @return array
+ */
+ function _squareReduce($x, $n, $mode)
+ {
+ if ($mode == self::MONTGOMERY) {
+ return $this->_montgomeryMultiply($x, $x, $n);
+ }
+ return $this->_reduce($this->_square($x), $n, $mode);
+ }
+
+ /**
+ * Modulos for Powers of Two
+ *
+ * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
+ * we'll just use this function as a wrapper for doing that.
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param \phpseclib\Math\BigInteger
+ * @return \phpseclib\Math\BigInteger
+ */
+ function _mod2($n)
+ {
+ $temp = new static();
+ $temp->value = array(1);
+ return $this->bitwise_and($n->subtract($temp));
+ }
+
+ /**
+ * Barrett Modular Reduction
+ *
+ * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly,
+ * so as not to require negative numbers (initially, this script didn't support negative numbers).
+ *
+ * Employs "folding", as described at
+ * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from
+ * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
+ *
+ * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
+ * usable on account of (1) its not using reasonable radix points as discussed in
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
+ * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that
+ * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
+ * comments for details.
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $n
+ * @param array $m
+ * @return array
+ */
+ function _barrett($n, $m)
+ {
+ static $cache = array(
+ self::VARIABLE => array(),
+ self::DATA => array()
+ );
+
+ $m_length = count($m);
+
+ // if ($this->_compare($n, $this->_square($m)) >= 0) {
+ if (count($n) > 2 * $m_length) {
+ $lhs = new static();
+ $rhs = new static();
+ $lhs->value = $n;
+ $rhs->value = $m;
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ }
+
+ // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
+ if ($m_length < 5) {
+ return $this->_regularBarrett($n, $m);
+ }
+
+ // n = 2 * m.length
+
+ if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
+ $key = count($cache[self::VARIABLE]);
+ $cache[self::VARIABLE][] = $m;
+
+ $lhs = new static();
+ $lhs_value = &$lhs->value;
+ $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1));
+ $lhs_value[] = 1;
+ $rhs = new static();
+ $rhs->value = $m;
+
+ list($u, $m1) = $lhs->divide($rhs);
+ $u = $u->value;
+ $m1 = $m1->value;
+
+ $cache[self::DATA][] = array(
+ 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
+ 'm1'=> $m1 // m.length
+ );
+ } else {
+ extract($cache[self::DATA][$key]);
+ }
+
+ $cutoff = $m_length + ($m_length >> 1);
+ $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1)
+ $msd = array_slice($n, $cutoff); // m.length >> 1
+ $lsd = $this->_trim($lsd);
+ $temp = $this->_multiply($msd, false, $m1, false);
+ $n = $this->_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1
+
+ if ($m_length & 1) {
+ return $this->_regularBarrett($n[self::VALUE], $m);
+ }
+
+ // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
+ $temp = array_slice($n[self::VALUE], $m_length - 1);
+ // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
+ // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
+ $temp = $this->_multiply($temp, false, $u, false);
+ // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
+ // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
+ $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1);
+ // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
+ // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1)
+ $temp = $this->_multiply($temp, false, $m, false);
+
+ // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
+ // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop
+ // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
+
+ $result = $this->_subtract($n[self::VALUE], false, $temp[self::VALUE], false);
+
+ while ($this->_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) {
+ $result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $m, false);
+ }
+
+ return $result[self::VALUE];
+ }
+
+ /**
+ * (Regular) Barrett Modular Reduction
+ *
+ * For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this
+ * is that this function does not fold the denominator into a smaller form.
+ *
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $n
+ * @return array
+ */
+ function _regularBarrett($x, $n)
+ {
+ static $cache = array(
+ self::VARIABLE => array(),
+ self::DATA => array()
+ );
+
+ $n_length = count($n);
+
+ if (count($x) > 2 * $n_length) {
+ $lhs = new static();
+ $rhs = new static();
+ $lhs->value = $x;
+ $rhs->value = $n;
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ }
+
+ if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
+ $key = count($cache[self::VARIABLE]);
+ $cache[self::VARIABLE][] = $n;
+ $lhs = new static();
+ $lhs_value = &$lhs->value;
+ $lhs_value = $this->_array_repeat(0, 2 * $n_length);
+ $lhs_value[] = 1;
+ $rhs = new static();
+ $rhs->value = $n;
+ list($temp, ) = $lhs->divide($rhs); // m.length
+ $cache[self::DATA][] = $temp->value;
+ }
+
+ // 2 * m.length - (m.length - 1) = m.length + 1
+ $temp = array_slice($x, $n_length - 1);
+ // (m.length + 1) + m.length = 2 * m.length + 1
+ $temp = $this->_multiply($temp, false, $cache[self::DATA][$key], false);
+ // (2 * m.length + 1) - (m.length - 1) = m.length + 2
+ $temp = array_slice($temp[self::VALUE], $n_length + 1);
+
+ // m.length + 1
+ $result = array_slice($x, 0, $n_length + 1);
+ // m.length + 1
+ $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1);
+ // $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1)
+
+ if ($this->_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) {
+ $corrector_value = $this->_array_repeat(0, $n_length + 1);
+ $corrector_value[count($corrector_value)] = 1;
+ $result = $this->_add($result, false, $corrector_value, false);
+ $result = $result[self::VALUE];
+ }
+
+ // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
+ $result = $this->_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]);
+ while ($this->_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) {
+ $result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $n, false);
+ }
+
+ return $result[self::VALUE];
+ }
+
+ /**
+ * Performs long multiplication up to $stop digits
+ *
+ * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
+ *
+ * @see self::_regularBarrett()
+ * @param array $x_value
+ * @param bool $x_negative
+ * @param array $y_value
+ * @param bool $y_negative
+ * @param int $stop
+ * @return array
+ * @access private
+ */
+ function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
+ {
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+
+ if (!$x_length || !$y_length) { // a 0 is being multiplied
+ return array(
+ self::VALUE => array(),
+ self::SIGN => false
+ );
+ }
+
+ if ($x_length < $y_length) {
+ $temp = $x_value;
+ $x_value = $y_value;
+ $y_value = $temp;
+
+ $x_length = count($x_value);
+ $y_length = count($y_value);
+ }
+
+ $product_value = $this->_array_repeat(0, $x_length + $y_length);
+
+ // the following for loop could be removed if the for loop following it
+ // (the one with nested for loops) initially set $i to 0, but
+ // doing so would also make the result in one set of unnecessary adds,
+ // since on the outermost loops first pass, $product->value[$k] is going
+ // to always be 0
+
+ $carry = 0;
+
+ for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
+ $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
+ }
+
+ if ($j < $stop) {
+ $product_value[$j] = $carry;
+ }
+
+ // the above for loop is what the previous comment was talking about. the
+ // following for loop is the "one with nested for loops"
+
+ for ($i = 1; $i < $y_length; ++$i) {
+ $carry = 0;
+
+ for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
+ $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
+ }
+
+ if ($k < $stop) {
+ $product_value[$k] = $carry;
+ }
+ }
+
+ return array(
+ self::VALUE => $this->_trim($product_value),
+ self::SIGN => $x_negative != $y_negative
+ );
+ }
+
+ /**
+ * Montgomery Modular Reduction
+ *
+ * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n.
+ * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
+ * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
+ * to work correctly.
+ *
+ * @see self::_prepMontgomery()
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $n
+ * @return array
+ */
+ function _montgomery($x, $n)
+ {
+ static $cache = array(
+ self::VARIABLE => array(),
+ self::DATA => array()
+ );
+
+ if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
+ $key = count($cache[self::VARIABLE]);
+ $cache[self::VARIABLE][] = $x;
+ $cache[self::DATA][] = $this->_modInverse67108864($n);
+ }
+
+ $k = count($n);
+
+ $result = array(self::VALUE => $x);
+
+ for ($i = 0; $i < $k; ++$i) {
+ $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key];
+ $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
+ $temp = $this->_regularMultiply(array($temp), $n);
+ $temp = array_merge($this->_array_repeat(0, $i), $temp);
+ $result = $this->_add($result[self::VALUE], false, $temp, false);
+ }
+
+ $result[self::VALUE] = array_slice($result[self::VALUE], $k);
+
+ if ($this->_compare($result, false, $n, false) >= 0) {
+ $result = $this->_subtract($result[self::VALUE], false, $n, false);
+ }
+
+ return $result[self::VALUE];
+ }
+
+ /**
+ * Montgomery Multiply
+ *
+ * Interleaves the montgomery reduction and long multiplication algorithms together as described in
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
+ *
+ * @see self::_prepMontgomery()
+ * @see self::_montgomery()
+ * @access private
+ * @param array $x
+ * @param array $y
+ * @param array $m
+ * @return array
+ */
+ function _montgomeryMultiply($x, $y, $m)
+ {
+ $temp = $this->_multiply($x, false, $y, false);
+ return $this->_montgomery($temp[self::VALUE], $m);
+
+ // the following code, although not callable, can be run independently of the above code
+ // although the above code performed better in my benchmarks the following could might
+ // perform better under different circumstances. in lieu of deleting it it's just been
+ // made uncallable
+
+ static $cache = array(
+ self::VARIABLE => array(),
+ self::DATA => array()
+ );
+
+ if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
+ $key = count($cache[self::VARIABLE]);
+ $cache[self::VARIABLE][] = $m;
+ $cache[self::DATA][] = $this->_modInverse67108864($m);
+ }
+
+ $n = max(count($x), count($y), count($m));
+ $x = array_pad($x, $n, 0);
+ $y = array_pad($y, $n, 0);
+ $m = array_pad($m, $n, 0);
+ $a = array(self::VALUE => $this->_array_repeat(0, $n + 1));
+ for ($i = 0; $i < $n; ++$i) {
+ $temp = $a[self::VALUE][0] + $x[$i] * $y[0];
+ $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
+ $temp = $temp * $cache[self::DATA][$key];
+ $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
+ $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
+ $a = $this->_add($a[self::VALUE], false, $temp[self::VALUE], false);
+ $a[self::VALUE] = array_slice($a[self::VALUE], 1);
+ }
+ if ($this->_compare($a[self::VALUE], false, $m, false) >= 0) {
+ $a = $this->_subtract($a[self::VALUE], false, $m, false);
+ }
+ return $a[self::VALUE];
+ }
+
+ /**
+ * Prepare a number for use in Montgomery Modular Reductions
+ *
+ * @see self::_montgomery()
+ * @see self::_slidingWindow()
+ * @access private
+ * @param array $x
+ * @param array $n
+ * @return array
+ */
+ function _prepMontgomery($x, $n)
+ {
+ $lhs = new static();
+ $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x);
+ $rhs = new static();
+ $rhs->value = $n;
+
+ list(, $temp) = $lhs->divide($rhs);
+ return $temp->value;
+ }
+
+ /**
+ * Modular Inverse of a number mod 2**26 (eg. 67108864)
+ *
+ * Based off of the bnpInvDigit function implemented and justified in the following URL:
+ *
+ * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
+ *
+ * The following URL provides more info:
+ *
+ * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
+ *
+ * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For
+ * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
+ * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
+ * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that
+ * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the
+ * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to
+ * 40 bits, which only 64-bit floating points will support.
+ *
+ * Thanks to Pedro Gimeno Fortea for input!
+ *
+ * @see self::_montgomery()
+ * @access private
+ * @param array $x
+ * @return int
+ */
+ function _modInverse67108864($x) // 2**26 == 67,108,864
+ {
+ $x = -$x[0];
+ $result = $x & 0x3; // x**-1 mod 2**2
+ $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
+ $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
+ $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
+ $result = fmod($result * (2 - fmod($x * $result, self::$baseFull)), self::$baseFull); // x**-1 mod 2**26
+ return $result & self::$maxDigit;
+ }
+
+ /**
+ * Calculates modular inverses.
+ *
+ * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger(30);
+ * $b = new \phpseclib\Math\BigInteger(17);
+ *
+ * $c = $a->modInverse($b);
+ * echo $c->toString(); // outputs 4
+ *
+ * echo "\r\n";
+ *
+ * $d = $a->multiply($c);
+ * list(, $d) = $d->divide($b);
+ * echo $d; // outputs 1 (as per the definition of modular inverse)
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $n
+ * @return \phpseclib\Math\BigInteger|false
+ * @access public
+ * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
+ */
+ function modInverse($n)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_invert($this->value, $n->value);
+
+ return ($temp->value === false) ? false : $this->_normalize($temp);
+ }
+
+ static $zero, $one;
+ if (!isset($zero)) {
+ $zero = new static();
+ $one = new static(1);
+ }
+
+ // $x mod -$n == $x mod $n.
+ $n = $n->abs();
+
+ if ($this->compare($zero) < 0) {
+ $temp = $this->abs();
+ $temp = $temp->modInverse($n);
+ return $this->_normalize($n->subtract($temp));
+ }
+
+ extract($this->extendedGCD($n));
+
+ if (!$gcd->equals($one)) {
+ return false;
+ }
+
+ $x = $x->compare($zero) < 0 ? $x->add($n) : $x;
+
+ return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x);
+ }
+
+ /**
+ * Calculates the greatest common divisor and Bezout's identity.
+ *
+ * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
+ * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
+ * combination is returned is dependent upon which mode is in use. See
+ * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger(693);
+ * $b = new \phpseclib\Math\BigInteger(609);
+ *
+ * extract($a->extendedGCD($b));
+ *
+ * echo $gcd->toString() . "\r\n"; // outputs 21
+ * echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $n
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal Calculates the GCD using the binary xGCD algorithim described in
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes,
+ * the more traditional algorithim requires "relatively costly multiple-precision divisions".
+ */
+ function extendedGCD($n)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ extract(gmp_gcdext($this->value, $n->value));
+
+ return array(
+ 'gcd' => $this->_normalize(new static($g)),
+ 'x' => $this->_normalize(new static($s)),
+ 'y' => $this->_normalize(new static($t))
+ );
+ case self::MODE_BCMATH:
+ // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
+ // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is,
+ // the basic extended euclidean algorithim is what we're using.
+
+ $u = $this->value;
+ $v = $n->value;
+
+ $a = '1';
+ $b = '0';
+ $c = '0';
+ $d = '1';
+
+ while (bccomp($v, '0', 0) != 0) {
+ $q = bcdiv($u, $v, 0);
+
+ $temp = $u;
+ $u = $v;
+ $v = bcsub($temp, bcmul($v, $q, 0), 0);
+
+ $temp = $a;
+ $a = $c;
+ $c = bcsub($temp, bcmul($a, $q, 0), 0);
+
+ $temp = $b;
+ $b = $d;
+ $d = bcsub($temp, bcmul($b, $q, 0), 0);
+ }
+
+ return array(
+ 'gcd' => $this->_normalize(new static($u)),
+ 'x' => $this->_normalize(new static($a)),
+ 'y' => $this->_normalize(new static($b))
+ );
+ }
+
+ $y = $n->copy();
+ $x = $this->copy();
+ $g = new static();
+ $g->value = array(1);
+
+ while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) {
+ $x->_rshift(1);
+ $y->_rshift(1);
+ $g->_lshift(1);
+ }
+
+ $u = $x->copy();
+ $v = $y->copy();
+
+ $a = new static();
+ $b = new static();
+ $c = new static();
+ $d = new static();
+
+ $a->value = $d->value = $g->value = array(1);
+ $b->value = $c->value = array();
+
+ while (!empty($u->value)) {
+ while (!($u->value[0] & 1)) {
+ $u->_rshift(1);
+ if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) {
+ $a = $a->add($y);
+ $b = $b->subtract($x);
+ }
+ $a->_rshift(1);
+ $b->_rshift(1);
+ }
+
+ while (!($v->value[0] & 1)) {
+ $v->_rshift(1);
+ if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) {
+ $c = $c->add($y);
+ $d = $d->subtract($x);
+ }
+ $c->_rshift(1);
+ $d->_rshift(1);
+ }
+
+ if ($u->compare($v) >= 0) {
+ $u = $u->subtract($v);
+ $a = $a->subtract($c);
+ $b = $b->subtract($d);
+ } else {
+ $v = $v->subtract($u);
+ $c = $c->subtract($a);
+ $d = $d->subtract($b);
+ }
+ }
+
+ return array(
+ 'gcd' => $this->_normalize($g->multiply($v)),
+ 'x' => $this->_normalize($c),
+ 'y' => $this->_normalize($d)
+ );
+ }
+
+ /**
+ * Calculates the greatest common divisor
+ *
+ * Say you have 693 and 609. The GCD is 21.
+ *
+ * Here's an example:
+ * <code>
+ * <?php
+ * $a = new \phpseclib\Math\BigInteger(693);
+ * $b = new \phpseclib\Math\BigInteger(609);
+ *
+ * $gcd = a->extendedGCD($b);
+ *
+ * echo $gcd->toString() . "\r\n"; // outputs 21
+ * ?>
+ * </code>
+ *
+ * @param \phpseclib\Math\BigInteger $n
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function gcd($n)
+ {
+ extract($this->extendedGCD($n));
+ return $gcd;
+ }
+
+ /**
+ * Absolute value.
+ *
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function abs()
+ {
+ $temp = new static();
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp->value = gmp_abs($this->value);
+ break;
+ case self::MODE_BCMATH:
+ $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value;
+ break;
+ default:
+ $temp->value = $this->value;
+ }
+
+ return $temp;
+ }
+
+ /**
+ * Compares two numbers.
+ *
+ * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is
+ * demonstrated thusly:
+ *
+ * $x > $y: $x->compare($y) > 0
+ * $x < $y: $x->compare($y) < 0
+ * $x == $y: $x->compare($y) == 0
+ *
+ * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
+ *
+ * @param \phpseclib\Math\BigInteger $y
+ * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
+ * @access public
+ * @see self::equals()
+ * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
+ */
+ function compare($y)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $r = gmp_cmp($this->value, $y->value);
+ if ($r < -1) {
+ $r = -1;
+ }
+ if ($r > 1) {
+ $r = 1;
+ }
+ return $r;
+ case self::MODE_BCMATH:
+ return bccomp($this->value, $y->value, 0);
+ }
+
+ return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative);
+ }
+
+ /**
+ * Compares two numbers.
+ *
+ * @param array $x_value
+ * @param bool $x_negative
+ * @param array $y_value
+ * @param bool $y_negative
+ * @return int
+ * @see self::compare()
+ * @access private
+ */
+ function _compare($x_value, $x_negative, $y_value, $y_negative)
+ {
+ if ($x_negative != $y_negative) {
+ return (!$x_negative && $y_negative) ? 1 : -1;
+ }
+
+ $result = $x_negative ? -1 : 1;
+
+ if (count($x_value) != count($y_value)) {
+ return (count($x_value) > count($y_value)) ? $result : -$result;
+ }
+ $size = max(count($x_value), count($y_value));
+
+ $x_value = array_pad($x_value, $size, 0);
+ $y_value = array_pad($y_value, $size, 0);
+
+ for ($i = count($x_value) - 1; $i >= 0; --$i) {
+ if ($x_value[$i] != $y_value[$i]) {
+ return ($x_value[$i] > $y_value[$i]) ? $result : -$result;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Tests the equality of two numbers.
+ *
+ * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
+ *
+ * @param \phpseclib\Math\BigInteger $x
+ * @return bool
+ * @access public
+ * @see self::compare()
+ */
+ function equals($x)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ return gmp_cmp($this->value, $x->value) == 0;
+ default:
+ return $this->value === $x->value && $this->is_negative == $x->is_negative;
+ }
+ }
+
+ /**
+ * Set Precision
+ *
+ * Some bitwise operations give different results depending on the precision being used. Examples include left
+ * shift, not, and rotates.
+ *
+ * @param int $bits
+ * @access public
+ */
+ function setPrecision($bits)
+ {
+ $this->precision = $bits;
+ if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) {
+ $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
+ } else {
+ $this->bitmask = new static(bcpow('2', $bits, 0));
+ }
+
+ $temp = $this->_normalize($this);
+ $this->value = $temp->value;
+ }
+
+ /**
+ * Logical And
+ *
+ * @param \phpseclib\Math\BigInteger $x
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return \phpseclib\Math\BigInteger
+ */
+ function bitwise_and($x)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_and($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case self::MODE_BCMATH:
+ $left = $this->toBytes();
+ $right = $x->toBytes();
+
+ $length = max(strlen($left), strlen($right));
+
+ $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new static($left & $right, 256));
+ }
+
+ $result = $this->copy();
+
+ $length = min(count($x->value), count($this->value));
+
+ $result->value = array_slice($result->value, 0, $length);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $result->value[$i]&= $x->value[$i];
+ }
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Or
+ *
+ * @param \phpseclib\Math\BigInteger $x
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return \phpseclib\Math\BigInteger
+ */
+ function bitwise_or($x)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_or($this->value, $x->value);
+
+ return $this->_normalize($temp);
+ case self::MODE_BCMATH:
+ $left = $this->toBytes();
+ $right = $x->toBytes();
+
+ $length = max(strlen($left), strlen($right));
+
+ $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new static($left | $right, 256));
+ }
+
+ $length = max(count($this->value), count($x->value));
+ $result = $this->copy();
+ $result->value = array_pad($result->value, $length, 0);
+ $x->value = array_pad($x->value, $length, 0);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $result->value[$i]|= $x->value[$i];
+ }
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Exclusive-Or
+ *
+ * @param \phpseclib\Math\BigInteger $x
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return \phpseclib\Math\BigInteger
+ */
+ function bitwise_xor($x)
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ $temp = new static();
+ $temp->value = gmp_xor(gmp_abs($this->value), gmp_abs($x->value));
+ return $this->_normalize($temp);
+ case self::MODE_BCMATH:
+ $left = $this->toBytes();
+ $right = $x->toBytes();
+
+ $length = max(strlen($left), strlen($right));
+
+ $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
+ $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new static($left ^ $right, 256));
+ }
+
+ $length = max(count($this->value), count($x->value));
+ $result = $this->copy();
+ $result->is_negative = false;
+ $result->value = array_pad($result->value, $length, 0);
+ $x->value = array_pad($x->value, $length, 0);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $result->value[$i]^= $x->value[$i];
+ }
+
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Not
+ *
+ * @access public
+ * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
+ * @return \phpseclib\Math\BigInteger
+ */
+ function bitwise_not()
+ {
+ // calculuate "not" without regard to $this->precision
+ // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
+ $temp = $this->toBytes();
+ if ($temp == '') {
+ return $this->_normalize(new static());
+ }
+ $pre_msb = decbin(ord($temp[0]));
+ $temp = ~$temp;
+ $msb = decbin(ord($temp[0]));
+ if (strlen($msb) == 8) {
+ $msb = substr($msb, strpos($msb, '0'));
+ }
+ $temp[0] = chr(bindec($msb));
+
+ // see if we need to add extra leading 1's
+ $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
+ $new_bits = $this->precision - $current_bits;
+ if ($new_bits <= 0) {
+ return $this->_normalize(new static($temp, 256));
+ }
+
+ // generate as many leading 1's as we need to.
+ $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);
+ $this->_base256_lshift($leading_ones, $current_bits);
+
+ $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
+
+ return $this->_normalize(new static($leading_ones | $temp, 256));
+ }
+
+ /**
+ * Logical Right Shift
+ *
+ * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
+ *
+ * @param int $shift
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal The only version that yields any speed increases is the internal version.
+ */
+ function bitwise_rightShift($shift)
+ {
+ $temp = new static();
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ static $two;
+
+ if (!isset($two)) {
+ $two = gmp_init('2');
+ }
+
+ $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
+
+ break;
+ case self::MODE_BCMATH:
+ $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0);
+
+ break;
+ default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten
+ // and I don't want to do that...
+ $temp->value = $this->value;
+ $temp->_rshift($shift);
+ }
+
+ return $this->_normalize($temp);
+ }
+
+ /**
+ * Logical Left Shift
+ *
+ * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
+ *
+ * @param int $shift
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal The only version that yields any speed increases is the internal version.
+ */
+ function bitwise_leftShift($shift)
+ {
+ $temp = new static();
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ static $two;
+
+ if (!isset($two)) {
+ $two = gmp_init('2');
+ }
+
+ $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
+
+ break;
+ case self::MODE_BCMATH:
+ $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0);
+
+ break;
+ default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
+ // and I don't want to do that...
+ $temp->value = $this->value;
+ $temp->_lshift($shift);
+ }
+
+ return $this->_normalize($temp);
+ }
+
+ /**
+ * Logical Left Rotate
+ *
+ * Instead of the top x bits being dropped they're appended to the shifted bit string.
+ *
+ * @param int $shift
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function bitwise_leftRotate($shift)
+ {
+ $bits = $this->toBytes();
+
+ if ($this->precision > 0) {
+ $precision = $this->precision;
+ if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
+ $mask = $this->bitmask->subtract(new static(1));
+ $mask = $mask->toBytes();
+ } else {
+ $mask = $this->bitmask->toBytes();
+ }
+ } else {
+ $temp = ord($bits[0]);
+ for ($i = 0; $temp >> $i; ++$i) {
+ }
+ $precision = 8 * strlen($bits) - 8 + $i;
+ $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);
+ }
+
+ if ($shift < 0) {
+ $shift+= $precision;
+ }
+ $shift%= $precision;
+
+ if (!$shift) {
+ return $this->copy();
+ }
+
+ $left = $this->bitwise_leftShift($shift);
+ $left = $left->bitwise_and(new static($mask, 256));
+ $right = $this->bitwise_rightShift($precision - $shift);
+ $result = MATH_BIGINTEGER_MODE != self::MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);
+ return $this->_normalize($result);
+ }
+
+ /**
+ * Logical Right Rotate
+ *
+ * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
+ *
+ * @param int $shift
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ */
+ function bitwise_rightRotate($shift)
+ {
+ return $this->bitwise_leftRotate(-$shift);
+ }
+
+ /**
+ * Generates a random BigInteger
+ *
+ * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
+ *
+ * @param int $length
+ * @return \phpseclib\Math\BigInteger
+ * @access private
+ */
+ function _random_number_helper($size)
+ {
+ if (class_exists('\phpseclib\Crypt\Random')) {
+ $random = Random::string($size);
+ } else {
+ $random = '';
+
+ if ($size & 1) {
+ $random.= chr(mt_rand(0, 255));
+ }
+
+ $blocks = $size >> 1;
+ for ($i = 0; $i < $blocks; ++$i) {
+ // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
+ $random.= pack('n', mt_rand(0, 0xFFFF));
+ }
+ }
+
+ return new static($random, 256);
+ }
+
+ /**
+ * Generate a random number
+ *
+ * Returns a random number between $min and $max where $min and $max
+ * can be defined using one of the two methods:
+ *
+ * $min->random($max)
+ * $max->random($min)
+ *
+ * @param \phpseclib\Math\BigInteger $arg1
+ * @param \phpseclib\Math\BigInteger $arg2
+ * @return \phpseclib\Math\BigInteger
+ * @access public
+ * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a BigInteger object.
+ * That method is still supported for BC purposes.
+ */
+ function random($arg1, $arg2 = false)
+ {
+ if ($arg1 === false) {
+ return false;
+ }
+
+ if ($arg2 === false) {
+ $max = $arg1;
+ $min = $this;
+ } else {
+ $min = $arg1;
+ $max = $arg2;
+ }
+
+ $compare = $max->compare($min);
+
+ if (!$compare) {
+ return $this->_normalize($min);
+ } elseif ($compare < 0) {
+ // if $min is bigger then $max, swap $min and $max
+ $temp = $max;
+ $max = $min;
+ $min = $temp;
+ }
+
+ static $one;
+ if (!isset($one)) {
+ $one = new static(1);
+ }
+
+ $max = $max->subtract($min->subtract($one));
+ $size = strlen(ltrim($max->toBytes(), chr(0)));
+
+ /*
+ doing $random % $max doesn't work because some numbers will be more likely to occur than others.
+ eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
+ would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
+ not all numbers would be equally likely. some would be more likely than others.
+
+ creating a whole new random number until you find one that is within the range doesn't work
+ because, for sufficiently small ranges, the likelihood that you'd get a number within that range
+ would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
+ would be pretty high that $random would be greater than $max.
+
+ phpseclib works around this using the technique described here:
+
+ http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
+ */
+ $random_max = new static(chr(1) . str_repeat("\0", $size), 256);
+ $random = $this->_random_number_helper($size);
+
+ list($max_multiple) = $random_max->divide($max);
+ $max_multiple = $max_multiple->multiply($max);
+
+ while ($random->compare($max_multiple) >= 0) {
+ $random = $random->subtract($max_multiple);
+ $random_max = $random_max->subtract($max_multiple);
+ $random = $random->bitwise_leftShift(8);
+ $random = $random->add($this->_random_number_helper(1));
+ $random_max = $random_max->bitwise_leftShift(8);
+ list($max_multiple) = $random_max->divide($max);
+ $max_multiple = $max_multiple->multiply($max);
+ }
+ list(, $random) = $random->divide($max);
+
+ return $this->_normalize($random->add($min));
+ }
+
+ /**
+ * Generate a random prime number.
+ *
+ * If there's not a prime within the given range, false will be returned.
+ * If more than $timeout seconds have elapsed, give up and return false.
+ *
+ * @param \phpseclib\Math\BigInteger $arg1
+ * @param \phpseclib\Math\BigInteger $arg2
+ * @param int $timeout
+ * @return Math_BigInteger|false
+ * @access public
+ * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
+ */
+ function randomPrime($arg1, $arg2 = false, $timeout = false)
+ {
+ if ($arg1 === false) {
+ return false;
+ }
+
+ if ($arg2 === false) {
+ $max = $arg1;
+ $min = $this;
+ } else {
+ $min = $arg1;
+ $max = $arg2;
+ }
+
+ $compare = $max->compare($min);
+
+ if (!$compare) {
+ return $min->isPrime() ? $min : false;
+ } elseif ($compare < 0) {
+ // if $min is bigger then $max, swap $min and $max
+ $temp = $max;
+ $max = $min;
+ $min = $temp;
+ }
+
+ static $one, $two;
+ if (!isset($one)) {
+ $one = new static(1);
+ $two = new static(2);
+ }
+
+ $start = time();
+
+ $x = $this->random($min, $max);
+
+ // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
+ if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) {
+ $p = new static();
+ $p->value = gmp_nextprime($x->value);
+
+ if ($p->compare($max) <= 0) {
+ return $p;
+ }
+
+ if (!$min->equals($x)) {
+ $x = $x->subtract($one);
+ }
+
+ return $x->randomPrime($min, $x);
+ }
+
+ if ($x->equals($two)) {
+ return $x;
+ }
+
+ $x->_make_odd();
+ if ($x->compare($max) > 0) {
+ // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
+ if ($min->equals($max)) {
+ return false;
+ }
+ $x = $min->copy();
+ $x->_make_odd();
+ }
+
+ $initial_x = $x->copy();
+
+ while (true) {
+ if ($timeout !== false && time() - $start > $timeout) {
+ return false;
+ }
+
+ if ($x->isPrime()) {
+ return $x;
+ }
+
+ $x = $x->add($two);
+
+ if ($x->compare($max) > 0) {
+ $x = $min->copy();
+ if ($x->equals($two)) {
+ return $x;
+ }
+ $x->_make_odd();
+ }
+
+ if ($x->equals($initial_x)) {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Make the current number odd
+ *
+ * If the current number is odd it'll be unchanged. If it's even, one will be added to it.
+ *
+ * @see self::randomPrime()
+ * @access private
+ */
+ function _make_odd()
+ {
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ gmp_setbit($this->value, 0);
+ break;
+ case self::MODE_BCMATH:
+ if ($this->value[strlen($this->value) - 1] % 2 == 0) {
+ $this->value = bcadd($this->value, '1');
+ }
+ break;
+ default:
+ $this->value[0] |= 1;
+ }
+ }
+
+ /**
+ * Checks a numer to see if it's prime
+ *
+ * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the
+ * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads
+ * on a website instead of just one.
+ *
+ * @param \phpseclib\Math\BigInteger $t
+ * @return bool
+ * @access public
+ * @internal Uses the
+ * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
+ * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}.
+ */
+ function isPrime($t = false)
+ {
+ $length = strlen($this->toBytes());
+
+ if (!$t) {
+ // see HAC 4.49 "Note (controlling the error probability)"
+ // @codingStandardsIgnoreStart
+ if ($length >= 163) { $t = 2; } // floor(1300 / 8)
+ else if ($length >= 106) { $t = 3; } // floor( 850 / 8)
+ else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8)
+ else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8)
+ else if ($length >= 56 ) { $t = 6; } // floor( 450 / 8)
+ else if ($length >= 50 ) { $t = 7; } // floor( 400 / 8)
+ else if ($length >= 43 ) { $t = 8; } // floor( 350 / 8)
+ else if ($length >= 37 ) { $t = 9; } // floor( 300 / 8)
+ else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8)
+ else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8)
+ else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8)
+ else { $t = 27; }
+ // @codingStandardsIgnoreEnd
+ }
+
+ // ie. gmp_testbit($this, 0)
+ // ie. isEven() or !isOdd()
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ return gmp_prob_prime($this->value, $t) != 0;
+ case self::MODE_BCMATH:
+ if ($this->value === '2') {
+ return true;
+ }
+ if ($this->value[strlen($this->value) - 1] % 2 == 0) {
+ return false;
+ }
+ break;
+ default:
+ if ($this->value == array(2)) {
+ return true;
+ }
+ if (~$this->value[0] & 1) {
+ return false;
+ }
+ }
+
+ static $primes, $zero, $one, $two;
+
+ if (!isset($primes)) {
+ $primes = array(
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997
+ );
+
+ if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
+ for ($i = 0; $i < count($primes); ++$i) {
+ $primes[$i] = new static($primes[$i]);
+ }
+ }
+
+ $zero = new static();
+ $one = new static(1);
+ $two = new static(2);
+ }
+
+ if ($this->equals($one)) {
+ return false;
+ }
+
+ // see HAC 4.4.1 "Random search for probable primes"
+ if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
+ foreach ($primes as $prime) {
+ list(, $r) = $this->divide($prime);
+ if ($r->equals($zero)) {
+ return $this->equals($prime);
+ }
+ }
+ } else {
+ $value = $this->value;
+ foreach ($primes as $prime) {
+ list(, $r) = $this->_divide_digit($value, $prime);
+ if (!$r) {
+ return count($value) == 1 && $value[0] == $prime;
+ }
+ }
+ }
+
+ $n = $this->copy();
+ $n_1 = $n->subtract($one);
+ $n_2 = $n->subtract($two);
+
+ $r = $n_1->copy();
+ $r_value = $r->value;
+ // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
+ if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
+ $s = 0;
+ // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
+ while ($r->value[strlen($r->value) - 1] % 2 == 0) {
+ $r->value = bcdiv($r->value, '2', 0);
+ ++$s;
+ }
+ } else {
+ for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
+ $temp = ~$r_value[$i] & 0xFFFFFF;
+ for ($j = 1; ($temp >> $j) & 1; ++$j) {
+ }
+ if ($j != 25) {
+ break;
+ }
+ }
+ $s = 26 * $i + $j;
+ $r->_rshift($s);
+ }
+
+ for ($i = 0; $i < $t; ++$i) {
+ $a = $this->random($two, $n_2);
+ $y = $a->modPow($r, $n);
+
+ if (!$y->equals($one) && !$y->equals($n_1)) {
+ for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) {
+ $y = $y->modPow($two, $n);
+ if ($y->equals($one)) {
+ return false;
+ }
+ }
+
+ if (!$y->equals($n_1)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Logical Left Shift
+ *
+ * Shifts BigInteger's by $shift bits.
+ *
+ * @param int $shift
+ * @access private
+ */
+ function _lshift($shift)
+ {
+ if ($shift == 0) {
+ return;
+ }
+
+ $num_digits = (int) ($shift / self::$base);
+ $shift %= self::$base;
+ $shift = 1 << $shift;
+
+ $carry = 0;
+
+ for ($i = 0; $i < count($this->value); ++$i) {
+ $temp = $this->value[$i] * $shift + $carry;
+ $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
+ $this->value[$i] = (int) ($temp - $carry * self::$baseFull);
+ }
+
+ if ($carry) {
+ $this->value[count($this->value)] = $carry;
+ }
+
+ while ($num_digits--) {
+ array_unshift($this->value, 0);
+ }
+ }
+
+ /**
+ * Logical Right Shift
+ *
+ * Shifts BigInteger's by $shift bits.
+ *
+ * @param int $shift
+ * @access private
+ */
+ function _rshift($shift)
+ {
+ if ($shift == 0) {
+ return;
+ }
+
+ $num_digits = (int) ($shift / self::$base);
+ $shift %= self::$base;
+ $carry_shift = self::$base - $shift;
+ $carry_mask = (1 << $shift) - 1;
+
+ if ($num_digits) {
+ $this->value = array_slice($this->value, $num_digits);
+ }
+
+ $carry = 0;
+
+ for ($i = count($this->value) - 1; $i >= 0; --$i) {
+ $temp = $this->value[$i] >> $shift | $carry;
+ $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
+ $this->value[$i] = $temp;
+ }
+
+ $this->value = $this->_trim($this->value);
+ }
+
+ /**
+ * Normalize
+ *
+ * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
+ *
+ * @param \phpseclib\Math\BigInteger
+ * @return \phpseclib\Math\BigInteger
+ * @see self::_trim()
+ * @access private
+ */
+ function _normalize($result)
+ {
+ $result->precision = $this->precision;
+ $result->bitmask = $this->bitmask;
+
+ switch (MATH_BIGINTEGER_MODE) {
+ case self::MODE_GMP:
+ if ($this->bitmask !== false) {
+ $result->value = gmp_and($result->value, $result->bitmask->value);
+ }
+
+ return $result;
+ case self::MODE_BCMATH:
+ if (!empty($result->bitmask->value)) {
+ $result->value = bcmod($result->value, $result->bitmask->value);
+ }
+
+ return $result;
+ }
+
+ $value = &$result->value;
+
+ if (!count($value)) {
+ $result->is_negative = false;
+ return $result;
+ }
+
+ $value = $this->_trim($value);
+
+ if (!empty($result->bitmask->value)) {
+ $length = min(count($value), count($this->bitmask->value));
+ $value = array_slice($value, 0, $length);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $value[$i] = $value[$i] & $this->bitmask->value[$i];
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Trim
+ *
+ * Removes leading zeros
+ *
+ * @param array $value
+ * @return \phpseclib\Math\BigInteger
+ * @access private
+ */
+ function _trim($value)
+ {
+ for ($i = count($value) - 1; $i >= 0; --$i) {
+ if ($value[$i]) {
+ break;
+ }
+ unset($value[$i]);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Array Repeat
+ *
+ * @param $input Array
+ * @param $multiplier mixed
+ * @return array
+ * @access private
+ */
+ function _array_repeat($input, $multiplier)
+ {
+ return ($multiplier) ? array_fill(0, $multiplier, $input) : array();
+ }
+
+ /**
+ * Logical Left Shift
+ *
+ * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
+ *
+ * @param $x String
+ * @param $shift Integer
+ * @return string
+ * @access private
+ */
+ function _base256_lshift(&$x, $shift)
+ {
+ if ($shift == 0) {
+ return;
+ }
+
+ $num_bytes = $shift >> 3; // eg. floor($shift/8)
+ $shift &= 7; // eg. $shift % 8
+
+ $carry = 0;
+ for ($i = strlen($x) - 1; $i >= 0; --$i) {
+ $temp = ord($x[$i]) << $shift | $carry;
+ $x[$i] = chr($temp);
+ $carry = $temp >> 8;
+ }
+ $carry = ($carry != 0) ? chr($carry) : '';
+ $x = $carry . $x . str_repeat(chr(0), $num_bytes);
+ }
+
+ /**
+ * Logical Right Shift
+ *
+ * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
+ *
+ * @param $x String
+ * @param $shift Integer
+ * @return string
+ * @access private
+ */
+ function _base256_rshift(&$x, $shift)
+ {
+ if ($shift == 0) {
+ $x = ltrim($x, chr(0));
+ return '';
+ }
+
+ $num_bytes = $shift >> 3; // eg. floor($shift/8)
+ $shift &= 7; // eg. $shift % 8
+
+ $remainder = '';
+ if ($num_bytes) {
+ $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes;
+ $remainder = substr($x, $start);
+ $x = substr($x, 0, -$num_bytes);
+ }
+
+ $carry = 0;
+ $carry_shift = 8 - $shift;
+ for ($i = 0; $i < strlen($x); ++$i) {
+ $temp = (ord($x[$i]) >> $shift) | $carry;
+ $carry = (ord($x[$i]) << $carry_shift) & 0xFF;
+ $x[$i] = chr($temp);
+ }
+ $x = ltrim($x, chr(0));
+
+ $remainder = chr($carry >> $carry_shift) . $remainder;
+
+ return ltrim($remainder, chr(0));
+ }
+
+ // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long
+ // at 32-bits, while java's longs are 64-bits.
+
+ /**
+ * Converts 32-bit integers to bytes.
+ *
+ * @param int $x
+ * @return string
+ * @access private
+ */
+ function _int2bytes($x)
+ {
+ return ltrim(pack('N', $x), chr(0));
+ }
+
+ /**
+ * Converts bytes to 32-bit integers
+ *
+ * @param string $x
+ * @return int
+ * @access private
+ */
+ function _bytes2int($x)
+ {
+ $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
+ return $temp['int'];
+ }
+
+ /**
+ * DER-encode an integer
+ *
+ * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
+ *
+ * @see self::modPow()
+ * @access private
+ * @param int $length
+ * @return string
+ */
+ function _encodeASN1Length($length)
+ {
+ if ($length <= 0x7F) {
+ return chr($length);
+ }
+
+ $temp = ltrim(pack('N', $length), chr(0));
+ return pack('Ca*', 0x80 | strlen($temp), $temp);
+ }
+
+ /**
+ * Single digit division
+ *
+ * Even if int64 is being used the division operator will return a float64 value
+ * if the dividend is not evenly divisible by the divisor. Since a float64 doesn't
+ * have the precision of int64 this is a problem so, when int64 is being used,
+ * we'll guarantee that the dividend is divisible by first subtracting the remainder.
+ *
+ * @access private
+ * @param int $x
+ * @param int $y
+ * @return int
+ */
+ function _safe_divide($x, $y)
+ {
+ if (self::$base === 26) {
+ return (int) ($x / $y);
+ }
+
+ // self::$base === 31
+ return ($x - ($x % $y)) / $y;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of SCP.
+ *
+ * PHP version 5
+ *
+ * The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
+ * if (!$ssh->login('username', 'password')) {
+ * exit('bad login');
+ * }
+ * $scp = new \phpseclib\Net\SCP($ssh);
+ *
+ * $scp->put('abcd', str_repeat('x', 1024*1024));
+ * ?>
+ * </code>
+ *
+ * @category Net
+ * @package SCP
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2010 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Net;
+
+/**
+ * Pure-PHP implementations of SCP.
+ *
+ * @package SCP
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class SCP
+{
+ /**#@+
+ * @access public
+ * @see \phpseclib\Net\SCP::put()
+ */
+ /**
+ * Reads data from a local file.
+ */
+ const SOURCE_LOCAL_FILE = 1;
+ /**
+ * Reads data from a string.
+ */
+ const SOURCE_STRING = 2;
+ /**#@-*/
+
+ /**#@+
+ * @access private
+ * @see \phpseclib\Net\SCP::_send()
+ * @see \phpseclib\Net\SCP::_receive()
+ */
+ /**
+ * SSH1 is being used.
+ */
+ const MODE_SSH1 = 1;
+ /**
+ * SSH2 is being used.
+ */
+ const MODE_SSH2 = 2;
+ /**#@-*/
+
+ /**
+ * SSH Object
+ *
+ * @var object
+ * @access private
+ */
+ var $ssh;
+
+ /**
+ * Packet Size
+ *
+ * @var int
+ * @access private
+ */
+ var $packet_size;
+
+ /**
+ * Mode
+ *
+ * @var int
+ * @access private
+ */
+ var $mode;
+
+ /**
+ * Default Constructor.
+ *
+ * Connects to an SSH server
+ *
+ * @param \phpseclib\Net\SSH1|\phpseclib\Net\SSH2 $ssh
+ * @return \phpseclib\Net\SCP
+ * @access public
+ */
+ function __construct($ssh)
+ {
+ if ($ssh instanceof SSH2) {
+ $this->mode = self::MODE_SSH2;
+ } elseif ($ssh instanceof SSH1) {
+ $this->packet_size = 50000;
+ $this->mode = self::MODE_SSH1;
+ } else {
+ return;
+ }
+
+ $this->ssh = $ssh;
+ }
+
+ /**
+ * Uploads a file to the SCP server.
+ *
+ * By default, \phpseclib\Net\SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
+ * So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SCP::get(), you will get a file, twelve bytes
+ * long, containing 'filename.ext' as its contents.
+ *
+ * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
+ * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
+ * large $remote_file will be, as well.
+ *
+ * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
+ * care of that, yourself.
+ *
+ * @param string $remote_file
+ * @param string $data
+ * @param int $mode
+ * @param callable $callback
+ * @return bool
+ * @access public
+ */
+ function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
+ {
+ if (!isset($this->ssh)) {
+ return false;
+ }
+
+ if (empty($remote_file)) {
+ user_error('remote_file cannot be blank', E_USER_NOTICE);
+ return false;
+ }
+
+ if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
+ return false;
+ }
+
+ $temp = $this->_receive();
+ if ($temp !== chr(0)) {
+ return false;
+ }
+
+ if ($this->mode == self::MODE_SSH2) {
+ $this->packet_size = $this->ssh->packet_size_client_to_server[SSH2::CHANNEL_EXEC] - 4;
+ }
+
+ $remote_file = basename($remote_file);
+
+ if ($mode == self::SOURCE_STRING) {
+ $size = strlen($data);
+ } else {
+ if (!is_file($data)) {
+ user_error("$data is not a valid file", E_USER_NOTICE);
+ return false;
+ }
+
+ $fp = @fopen($data, 'rb');
+ if (!$fp) {
+ return false;
+ }
+ $size = filesize($data);
+ }
+
+ $this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
+
+ $temp = $this->_receive();
+ if ($temp !== chr(0)) {
+ return false;
+ }
+
+ $sent = 0;
+ while ($sent < $size) {
+ $temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
+ $this->_send($temp);
+ $sent+= strlen($temp);
+
+ if (is_callable($callback)) {
+ call_user_func($callback, $sent);
+ }
+ }
+ $this->_close();
+
+ if ($mode != self::SOURCE_STRING) {
+ fclose($fp);
+ }
+
+ return true;
+ }
+
+ /**
+ * Downloads a file from the SCP server.
+ *
+ * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
+ * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
+ * operation
+ *
+ * @param string $remote_file
+ * @param string $local_file
+ * @return mixed
+ * @access public
+ */
+ function get($remote_file, $local_file = false)
+ {
+ if (!isset($this->ssh)) {
+ return false;
+ }
+
+ if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
+ return false;
+ }
+
+ $this->_send("\0");
+
+ if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
+ return false;
+ }
+
+ $this->_send("\0");
+
+ $size = 0;
+
+ if ($local_file !== false) {
+ $fp = @fopen($local_file, 'wb');
+ if (!$fp) {
+ return false;
+ }
+ }
+
+ $content = '';
+ while ($size < $info['size']) {
+ $data = $this->_receive();
+ // SCP usually seems to split stuff out into 16k chunks
+ $size+= strlen($data);
+
+ if ($local_file === false) {
+ $content.= $data;
+ } else {
+ fputs($fp, $data);
+ }
+ }
+
+ $this->_close();
+
+ if ($local_file !== false) {
+ fclose($fp);
+ return true;
+ }
+
+ return $content;
+ }
+
+ /**
+ * Sends a packet to an SSH server
+ *
+ * @param string $data
+ * @access private
+ */
+ function _send($data)
+ {
+ switch ($this->mode) {
+ case self::MODE_SSH2:
+ $this->ssh->_send_channel_packet(SSH2::CHANNEL_EXEC, $data);
+ break;
+ case self::MODE_SSH1:
+ $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
+ $this->ssh->_send_binary_packet($data);
+ }
+ }
+
+ /**
+ * Receives a packet from an SSH server
+ *
+ * @return string
+ * @access private
+ */
+ function _receive()
+ {
+ switch ($this->mode) {
+ case self::MODE_SSH2:
+ return $this->ssh->_get_channel_packet(SSH2::CHANNEL_EXEC, true);
+ case self::MODE_SSH1:
+ if (!$this->ssh->bitmap) {
+ return false;
+ }
+ while (true) {
+ $response = $this->ssh->_get_binary_packet();
+ switch ($response[SSH1::RESPONSE_TYPE]) {
+ case NET_SSH1_SMSG_STDOUT_DATA:
+ if (strlen($response[SSH1::RESPONSE_DATA]) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA]));
+ return $this->ssh->_string_shift($response[SSH1::RESPONSE_DATA], $length);
+ case NET_SSH1_SMSG_STDERR_DATA:
+ break;
+ case NET_SSH1_SMSG_EXITSTATUS:
+ $this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
+ fclose($this->ssh->fsock);
+ $this->ssh->bitmap = 0;
+ return false;
+ default:
+ user_error('Unknown packet received', E_USER_NOTICE);
+ return false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Closes the connection to an SSH server
+ *
+ * @access private
+ */
+ function _close()
+ {
+ switch ($this->mode) {
+ case self::MODE_SSH2:
+ $this->ssh->_close_channel(SSH2::CHANNEL_EXEC, true);
+ break;
+ case self::MODE_SSH1:
+ $this->ssh->disconnect();
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of SFTP.
+ *
+ * PHP version 5
+ *
+ * Currently only supports SFTPv2 and v3, which, according to wikipedia.org, "is the most widely used version,
+ * implemented by the popular OpenSSH SFTP server". If you want SFTPv4/5/6 support, provide me with access
+ * to an SFTPv4/5/6 server.
+ *
+ * The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $sftp = new \phpseclib\Net\SFTP('www.domain.tld');
+ * if (!$sftp->login('username', 'password')) {
+ * exit('Login Failed');
+ * }
+ *
+ * echo $sftp->pwd() . "\r\n";
+ * $sftp->put('filename.ext', 'hello, world!');
+ * print_r($sftp->nlist());
+ * ?>
+ * </code>
+ *
+ * @category Net
+ * @package SFTP
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2009 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Net;
+
+/**
+ * Pure-PHP implementations of SFTP.
+ *
+ * @package SFTP
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class SFTP extends SSH2
+{
+ /**
+ * SFTP channel constant
+ *
+ * \phpseclib\Net\SSH2::exec() uses 0 and \phpseclib\Net\SSH2::read() / \phpseclib\Net\SSH2::write() use 1.
+ *
+ * @see \phpseclib\Net\SSH2::_send_channel_packet()
+ * @see \phpseclib\Net\SSH2::_get_channel_packet()
+ * @access private
+ */
+ const CHANNEL = 0x100;
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Net\SFTP::put()
+ */
+ /**
+ * Reads data from a local file.
+ */
+ const SOURCE_LOCAL_FILE = 1;
+ /**
+ * Reads data from a string.
+ */
+ // this value isn't really used anymore but i'm keeping it reserved for historical reasons
+ const SOURCE_STRING = 2;
+ /**
+ * Reads data from callback:
+ * function callback($length) returns string to proceed, null for EOF
+ */
+ const SOURCE_CALLBACK = 16;
+ /**
+ * Resumes an upload
+ */
+ const RESUME = 4;
+ /**
+ * Append a local file to an already existing remote file
+ */
+ const RESUME_START = 8;
+ /**#@-*/
+
+ /**
+ * Packet Types
+ *
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $packet_types = array();
+
+ /**
+ * Status Codes
+ *
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $status_codes = array();
+
+ /**
+ * The Request ID
+ *
+ * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
+ * concurrent actions, so it's somewhat academic, here.
+ *
+ * @var boolean
+ * @see self::_send_sftp_packet()
+ * @access private
+ */
+ var $use_request_id = false;
+
+ /**
+ * The Packet Type
+ *
+ * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
+ * concurrent actions, so it's somewhat academic, here.
+ *
+ * @var int
+ * @see self::_get_sftp_packet()
+ * @access private
+ */
+ var $packet_type = -1;
+
+ /**
+ * Packet Buffer
+ *
+ * @var string
+ * @see self::_get_sftp_packet()
+ * @access private
+ */
+ var $packet_buffer = '';
+
+ /**
+ * Extensions supported by the server
+ *
+ * @var array
+ * @see self::_initChannel()
+ * @access private
+ */
+ var $extensions = array();
+
+ /**
+ * Server SFTP version
+ *
+ * @var int
+ * @see self::_initChannel()
+ * @access private
+ */
+ var $version;
+
+ /**
+ * Current working directory
+ *
+ * @var string
+ * @see self::realpath()
+ * @see self::chdir()
+ * @access private
+ */
+ var $pwd = false;
+
+ /**
+ * Packet Type Log
+ *
+ * @see self::getLog()
+ * @var array
+ * @access private
+ */
+ var $packet_type_log = array();
+
+ /**
+ * Packet Log
+ *
+ * @see self::getLog()
+ * @var array
+ * @access private
+ */
+ var $packet_log = array();
+
+ /**
+ * Error information
+ *
+ * @see self::getSFTPErrors()
+ * @see self::getLastSFTPError()
+ * @var array
+ * @access private
+ */
+ var $sftp_errors = array();
+
+ /**
+ * Stat Cache
+ *
+ * Rather than always having to open a directory and close it immediately there after to see if a file is a directory
+ * we'll cache the results.
+ *
+ * @see self::_update_stat_cache()
+ * @see self::_remove_from_stat_cache()
+ * @see self::_query_stat_cache()
+ * @var array
+ * @access private
+ */
+ var $stat_cache = array();
+
+ /**
+ * Max SFTP Packet Size
+ *
+ * @see self::__construct()
+ * @see self::get()
+ * @var array
+ * @access private
+ */
+ var $max_sftp_packet;
+
+ /**
+ * Stat Cache Flag
+ *
+ * @see self::disableStatCache()
+ * @see self::enableStatCache()
+ * @var bool
+ * @access private
+ */
+ var $use_stat_cache = true;
+
+ /**
+ * Sort Options
+ *
+ * @see self::_comparator()
+ * @see self::setListOrder()
+ * @var array
+ * @access private
+ */
+ var $sortOptions = array();
+
+ /**
+ * Canonicalization Flag
+ *
+ * Determines whether or not paths should be canonicalized before being
+ * passed on to the remote server.
+ *
+ * @see self::enablePathCanonicalization()
+ * @see self::disablePathCanonicalization()
+ * @see self::realpath()
+ * @var bool
+ * @access private
+ */
+ var $canonicalize_paths = true;
+
+ /**
+ * Request Buffers
+ *
+ * @see self::_get_sftp_packet()
+ * @var array
+ * @access private
+ */
+ var $requestBuffer = array();
+
+ /**
+ * Default Constructor.
+ *
+ * Connects to an SFTP server
+ *
+ * @param string $host
+ * @param int $port
+ * @param int $timeout
+ * @return \phpseclib\Net\SFTP
+ * @access public
+ */
+ function __construct($host, $port = 22, $timeout = 10)
+ {
+ parent::__construct($host, $port, $timeout);
+
+ $this->max_sftp_packet = 1 << 15;
+
+ $this->packet_types = array(
+ 1 => 'NET_SFTP_INIT',
+ 2 => 'NET_SFTP_VERSION',
+ /* the format of SSH_FXP_OPEN changed between SFTPv4 and SFTPv5+:
+ SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.1
+ pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 */
+ 3 => 'NET_SFTP_OPEN',
+ 4 => 'NET_SFTP_CLOSE',
+ 5 => 'NET_SFTP_READ',
+ 6 => 'NET_SFTP_WRITE',
+ 7 => 'NET_SFTP_LSTAT',
+ 9 => 'NET_SFTP_SETSTAT',
+ 11 => 'NET_SFTP_OPENDIR',
+ 12 => 'NET_SFTP_READDIR',
+ 13 => 'NET_SFTP_REMOVE',
+ 14 => 'NET_SFTP_MKDIR',
+ 15 => 'NET_SFTP_RMDIR',
+ 16 => 'NET_SFTP_REALPATH',
+ 17 => 'NET_SFTP_STAT',
+ /* the format of SSH_FXP_RENAME changed between SFTPv4 and SFTPv5+:
+ SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
+ pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */
+ 18 => 'NET_SFTP_RENAME',
+ 19 => 'NET_SFTP_READLINK',
+ 20 => 'NET_SFTP_SYMLINK',
+
+ 101=> 'NET_SFTP_STATUS',
+ 102=> 'NET_SFTP_HANDLE',
+ /* the format of SSH_FXP_NAME changed between SFTPv3 and SFTPv4+:
+ SFTPv4+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4
+ pre-SFTPv4 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7 */
+ 103=> 'NET_SFTP_DATA',
+ 104=> 'NET_SFTP_NAME',
+ 105=> 'NET_SFTP_ATTRS',
+
+ 200=> 'NET_SFTP_EXTENDED'
+ );
+ $this->status_codes = array(
+ 0 => 'NET_SFTP_STATUS_OK',
+ 1 => 'NET_SFTP_STATUS_EOF',
+ 2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
+ 3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
+ 4 => 'NET_SFTP_STATUS_FAILURE',
+ 5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
+ 6 => 'NET_SFTP_STATUS_NO_CONNECTION',
+ 7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
+ 8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
+ 9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
+ 10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
+ 11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
+ 12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
+ 13 => 'NET_SFTP_STATUS_NO_MEDIA',
+ 14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
+ 15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
+ 16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
+ 17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
+ 18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
+ 19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
+ 20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
+ 21 => 'NET_SFTP_STATUS_LINK_LOOP',
+ 22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
+ 23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
+ 24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
+ 25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
+ 26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
+ 27 => 'NET_SFTP_STATUS_DELETE_PENDING',
+ 28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
+ 29 => 'NET_SFTP_STATUS_OWNER_INVALID',
+ 30 => 'NET_SFTP_STATUS_GROUP_INVALID',
+ 31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
+ );
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
+ // the order, in this case, matters quite a lot - see \phpseclib\Net\SFTP::_parseAttributes() to understand why
+ $this->attributes = array(
+ 0x00000001 => 'NET_SFTP_ATTR_SIZE',
+ 0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
+ 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
+ 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
+ // 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
+ // yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
+ // two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
+ // that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
+ (-1 << 31) & 0xFFFFFFFF => 'NET_SFTP_ATTR_EXTENDED'
+ );
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
+ // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
+ // the array for that $this->open5_flags and similarly alter the constant names.
+ $this->open_flags = array(
+ 0x00000001 => 'NET_SFTP_OPEN_READ',
+ 0x00000002 => 'NET_SFTP_OPEN_WRITE',
+ 0x00000004 => 'NET_SFTP_OPEN_APPEND',
+ 0x00000008 => 'NET_SFTP_OPEN_CREATE',
+ 0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
+ 0x00000020 => 'NET_SFTP_OPEN_EXCL'
+ );
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
+ // see \phpseclib\Net\SFTP::_parseLongname() for an explanation
+ $this->file_types = array(
+ 1 => 'NET_SFTP_TYPE_REGULAR',
+ 2 => 'NET_SFTP_TYPE_DIRECTORY',
+ 3 => 'NET_SFTP_TYPE_SYMLINK',
+ 4 => 'NET_SFTP_TYPE_SPECIAL',
+ 5 => 'NET_SFTP_TYPE_UNKNOWN',
+ // the followin types were first defined for use in SFTPv5+
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
+ 6 => 'NET_SFTP_TYPE_SOCKET',
+ 7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
+ 8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
+ 9 => 'NET_SFTP_TYPE_FIFO'
+ );
+ $this->_define_array(
+ $this->packet_types,
+ $this->status_codes,
+ $this->attributes,
+ $this->open_flags,
+ $this->file_types
+ );
+
+ if (!defined('NET_SFTP_QUEUE_SIZE')) {
+ define('NET_SFTP_QUEUE_SIZE', 32);
+ }
+ }
+
+ /**
+ * Login
+ *
+ * @param string $username
+ * @param string $password
+ * @return bool
+ * @access public
+ */
+ function login($username)
+ {
+ $args = func_get_args();
+ if (!call_user_func_array(array(&$this, '_login'), $args)) {
+ return false;
+ }
+
+ $this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
+
+ $packet = pack(
+ 'CNa*N3',
+ NET_SSH2_MSG_CHANNEL_OPEN,
+ strlen('session'),
+ 'session',
+ self::CHANNEL,
+ $this->window_size,
+ 0x4000
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
+
+ $response = $this->_get_channel_packet(self::CHANNEL, true);
+ if ($response === false) {
+ return false;
+ }
+
+ $packet = pack(
+ 'CNNa*CNa*',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL],
+ strlen('subsystem'),
+ 'subsystem',
+ 1,
+ strlen('sftp'),
+ 'sftp'
+ );
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
+
+ $response = $this->_get_channel_packet(self::CHANNEL, true);
+ if ($response === false) {
+ // from PuTTY's psftp.exe
+ $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" .
+ "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" .
+ "exec sftp-server";
+ // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
+ // is redundant
+ $packet = pack(
+ 'CNNa*CNa*',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL],
+ strlen('exec'),
+ 'exec',
+ 1,
+ strlen($command),
+ $command
+ );
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
+
+ $response = $this->_get_channel_packet(self::CHANNEL, true);
+ if ($response === false) {
+ return false;
+ }
+ }
+
+ $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
+
+ if (!$this->_send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3")) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_VERSION) {
+ user_error('Expected SSH_FXP_VERSION');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nversion', $this->_string_shift($response, 4)));
+ $this->version = $version;
+ while (!empty($response)) {
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $key = $this->_string_shift($response, $length);
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $value = $this->_string_shift($response, $length);
+ $this->extensions[$key] = $value;
+ }
+
+ /*
+ SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
+ however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
+ not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
+ one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
+ 'newline@vandyke.com' would.
+ */
+ /*
+ if (isset($this->extensions['newline@vandyke.com'])) {
+ $this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
+ unset($this->extensions['newline@vandyke.com']);
+ }
+ */
+
+ $this->use_request_id = true;
+
+ /*
+ A Note on SFTPv4/5/6 support:
+ <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
+
+ "If the client wishes to interoperate with servers that support noncontiguous version
+ numbers it SHOULD send '3'"
+
+ Given that the server only sends its version number after the client has already done so, the above
+ seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the
+ most popular.
+
+ <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
+
+ "If the server did not send the "versions" extension, or the version-from-list was not included, the
+ server MAY send a status response describing the failure, but MUST then close the channel without
+ processing any further requests."
+
+ So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
+ a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements
+ v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
+ in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the
+ channel and reopen it with a new and updated SSH_FXP_INIT packet.
+ */
+ switch ($this->version) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return false;
+ }
+
+ $this->pwd = $this->_realpath('.');
+
+ $this->_update_stat_cache($this->pwd, array());
+
+ return true;
+ }
+
+ /**
+ * Disable the stat cache
+ *
+ * @access public
+ */
+ function disableStatCache()
+ {
+ $this->use_stat_cache = false;
+ }
+
+ /**
+ * Enable the stat cache
+ *
+ * @access public
+ */
+ function enableStatCache()
+ {
+ $this->use_stat_cache = true;
+ }
+
+ /**
+ * Clear the stat cache
+ *
+ * @access public
+ */
+ function clearStatCache()
+ {
+ $this->stat_cache = array();
+ }
+
+ /**
+ * Enable path canonicalization
+ *
+ * @access public
+ */
+ function enablePathCanonicalization()
+ {
+ $this->canonicalize_paths = true;
+ }
+
+ /**
+ * Enable path canonicalization
+ *
+ * @access public
+ */
+ function disablePathCanonicalization()
+ {
+ $this->canonicalize_paths = false;
+ }
+
+ /**
+ * Returns the current directory name
+ *
+ * @return mixed
+ * @access public
+ */
+ function pwd()
+ {
+ return $this->pwd;
+ }
+
+ /**
+ * Logs errors
+ *
+ * @param string $response
+ * @param int $status
+ * @access public
+ */
+ function _logError($response, $status = -1)
+ {
+ if ($status == -1) {
+ if (strlen($response) < 4) {
+ return;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ }
+
+ $error = $this->status_codes[$status];
+
+ if ($this->version > 2 || strlen($response) < 4) {
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->sftp_errors[] = $error . ': ' . $this->_string_shift($response, $length);
+ } else {
+ $this->sftp_errors[] = $error;
+ }
+ }
+
+ /**
+ * Returns canonicalized absolute pathname
+ *
+ * realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input
+ * path and returns the canonicalized absolute pathname.
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function realpath($path)
+ {
+ return $this->_realpath($path);
+ }
+
+ /**
+ * Canonicalize the Server-Side Path Name
+ *
+ * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
+ * the absolute (canonicalized) path.
+ *
+ * If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
+ *
+ * @see self::chdir()
+ * @see self::disablePathCanonicalization()
+ * @param string $path
+ * @return mixed
+ * @access private
+ */
+ function _realpath($path)
+ {
+ if (!$this->canonicalize_paths) {
+ return $path;
+ }
+
+ if ($this->pwd === false) {
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
+ if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_NAME:
+ // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
+ // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
+ // at is the first part and that part is defined the same in SFTP versions 3 through 6.
+ $this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ return $this->_string_shift($response, $length);
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ return false;
+ default:
+ user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
+ return false;
+ }
+ }
+
+ if ($path[0] != '/') {
+ $path = $this->pwd . '/' . $path;
+ }
+
+ $path = explode('/', $path);
+ $new = array();
+ foreach ($path as $dir) {
+ if (!strlen($dir)) {
+ continue;
+ }
+ switch ($dir) {
+ case '..':
+ array_pop($new);
+ case '.':
+ break;
+ default:
+ $new[] = $dir;
+ }
+ }
+
+ return '/' . implode('/', $new);
+ }
+
+ /**
+ * Changes the current directory
+ *
+ * @param string $dir
+ * @return bool
+ * @access public
+ */
+ function chdir($dir)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ // assume current dir if $dir is empty
+ if ($dir === '') {
+ $dir = './';
+ // suffix a slash if needed
+ } elseif ($dir[strlen($dir) - 1] != '/') {
+ $dir.= '/';
+ }
+
+ $dir = $this->_realpath($dir);
+
+ // confirm that $dir is, in fact, a valid directory
+ if ($this->use_stat_cache && is_array($this->_query_stat_cache($dir))) {
+ $this->pwd = $dir;
+ return true;
+ }
+
+ // we could do a stat on the alleged $dir to see if it's a directory but that doesn't tell us
+ // the currently logged in user has the appropriate permissions or not. maybe you could see if
+ // the file's uid / gid match the currently logged in user's uid / gid but how there's no easy
+ // way to get those with SFTP
+
+ if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
+ return false;
+ }
+
+ // see \phpseclib\Net\SFTP::nlist() for a more thorough explanation of the following
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ $handle = substr($response, 4);
+ break;
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ return false;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (!$this->_close_handle($handle)) {
+ return false;
+ }
+
+ $this->_update_stat_cache($dir, array());
+
+ $this->pwd = $dir;
+ return true;
+ }
+
+ /**
+ * Returns a list of files in the given directory
+ *
+ * @param string $dir
+ * @param bool $recursive
+ * @return mixed
+ * @access public
+ */
+ function nlist($dir = '.', $recursive = false)
+ {
+ return $this->_nlist_helper($dir, $recursive, '');
+ }
+
+ /**
+ * Helper method for nlist
+ *
+ * @param string $dir
+ * @param bool $recursive
+ * @param string $relativeDir
+ * @return mixed
+ * @access private
+ */
+ function _nlist_helper($dir, $recursive, $relativeDir)
+ {
+ $files = $this->_list($dir, false);
+
+ if (!$recursive || $files === false) {
+ return $files;
+ }
+
+ $result = array();
+ foreach ($files as $value) {
+ if ($value == '.' || $value == '..') {
+ if ($relativeDir == '') {
+ $result[] = $value;
+ }
+ continue;
+ }
+ if (is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $value)))) {
+ $temp = $this->_nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/');
+ $temp = is_array($temp) ? $temp : array();
+ $result = array_merge($result, $temp);
+ } else {
+ $result[] = $relativeDir . $value;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns a detailed list of files in the given directory
+ *
+ * @param string $dir
+ * @param bool $recursive
+ * @return mixed
+ * @access public
+ */
+ function rawlist($dir = '.', $recursive = false)
+ {
+ $files = $this->_list($dir, true);
+ if (!$recursive || $files === false) {
+ return $files;
+ }
+
+ static $depth = 0;
+
+ foreach ($files as $key => $value) {
+ if ($depth != 0 && $key == '..') {
+ unset($files[$key]);
+ continue;
+ }
+ $is_directory = false;
+ if ($key != '.' && $key != '..') {
+ if ($this->use_stat_cache) {
+ $is_directory = is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key)));
+ } else {
+ $stat = $this->lstat($dir . '/' . $key);
+ $is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY;
+ }
+ }
+
+ if ($is_directory) {
+ $depth++;
+ $files[$key] = $this->rawlist($dir . '/' . $key, true);
+ $depth--;
+ } else {
+ $files[$key] = (object) $value;
+ }
+ }
+
+ return $files;
+ }
+
+ /**
+ * Reads a list, be it detailed or not, of files in the given directory
+ *
+ * @param string $dir
+ * @param bool $raw
+ * @return mixed
+ * @access private
+ */
+ function _list($dir, $raw = true)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $dir = $this->_realpath($dir . '/');
+ if ($dir === false) {
+ return false;
+ }
+
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
+ if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
+ // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
+ // represent the length of the string and leave it at that
+ $handle = substr($response, 4);
+ break;
+ case NET_SFTP_STATUS:
+ // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
+ $this->_logError($response);
+ return false;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+
+ $this->_update_stat_cache($dir, array());
+
+ $contents = array();
+ while (true) {
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
+ // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
+ // SSH_MSG_CHANNEL_DATA messages is not known to me.
+ if (!$this->_send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_NAME:
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Ncount', $this->_string_shift($response, 4)));
+ for ($i = 0; $i < $count; $i++) {
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $shortname = $this->_string_shift($response, $length);
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $longname = $this->_string_shift($response, $length);
+ $attributes = $this->_parseAttributes($response);
+ if (!isset($attributes['type'])) {
+ $fileType = $this->_parseLongname($longname);
+ if ($fileType) {
+ $attributes['type'] = $fileType;
+ }
+ }
+ $contents[$shortname] = $attributes + array('filename' => $shortname);
+
+ if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) {
+ $this->_update_stat_cache($dir . '/' . $shortname, array());
+ } else {
+ if ($shortname == '..') {
+ $temp = $this->_realpath($dir . '/..') . '/.';
+ } else {
+ $temp = $dir . '/' . $shortname;
+ }
+ $this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
+ }
+ // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
+ // final SSH_FXP_STATUS packet should tell us that, already.
+ }
+ break;
+ case NET_SFTP_STATUS:
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_EOF) {
+ $this->_logError($response, $status);
+ return false;
+ }
+ break 2;
+ default:
+ user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
+ return false;
+ }
+ }
+
+ if (!$this->_close_handle($handle)) {
+ return false;
+ }
+
+ if (count($this->sortOptions)) {
+ uasort($contents, array(&$this, '_comparator'));
+ }
+
+ return $raw ? $contents : array_keys($contents);
+ }
+
+ /**
+ * Compares two rawlist entries using parameters set by setListOrder()
+ *
+ * Intended for use with uasort()
+ *
+ * @param array $a
+ * @param array $b
+ * @return int
+ * @access private
+ */
+ function _comparator($a, $b)
+ {
+ switch (true) {
+ case $a['filename'] === '.' || $b['filename'] === '.':
+ if ($a['filename'] === $b['filename']) {
+ return 0;
+ }
+ return $a['filename'] === '.' ? -1 : 1;
+ case $a['filename'] === '..' || $b['filename'] === '..':
+ if ($a['filename'] === $b['filename']) {
+ return 0;
+ }
+ return $a['filename'] === '..' ? -1 : 1;
+ case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY:
+ if (!isset($b['type'])) {
+ return 1;
+ }
+ if ($b['type'] !== $a['type']) {
+ return -1;
+ }
+ break;
+ case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY:
+ return 1;
+ }
+ foreach ($this->sortOptions as $sort => $order) {
+ if (!isset($a[$sort]) || !isset($b[$sort])) {
+ if (isset($a[$sort])) {
+ return -1;
+ }
+ if (isset($b[$sort])) {
+ return 1;
+ }
+ return 0;
+ }
+ switch ($sort) {
+ case 'filename':
+ $result = strcasecmp($a['filename'], $b['filename']);
+ if ($result) {
+ return $order === SORT_DESC ? -$result : $result;
+ }
+ break;
+ case 'permissions':
+ case 'mode':
+ $a[$sort]&= 07777;
+ $b[$sort]&= 07777;
+ default:
+ if ($a[$sort] === $b[$sort]) {
+ break;
+ }
+ return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort];
+ }
+ }
+ }
+
+ /**
+ * Defines how nlist() and rawlist() will be sorted - if at all.
+ *
+ * If sorting is enabled directories and files will be sorted independently with
+ * directories appearing before files in the resultant array that is returned.
+ *
+ * Any parameter returned by stat is a valid sort parameter for this function.
+ * Filename comparisons are case insensitive.
+ *
+ * Examples:
+ *
+ * $sftp->setListOrder('filename', SORT_ASC);
+ * $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC);
+ * $sftp->setListOrder(true);
+ * Separates directories from files but doesn't do any sorting beyond that
+ * $sftp->setListOrder();
+ * Don't do any sort of sorting
+ *
+ * @access public
+ */
+ function setListOrder()
+ {
+ $this->sortOptions = array();
+ $args = func_get_args();
+ if (empty($args)) {
+ return;
+ }
+ $len = count($args) & 0x7FFFFFFE;
+ for ($i = 0; $i < $len; $i+=2) {
+ $this->sortOptions[$args[$i]] = $args[$i + 1];
+ }
+ if (!count($this->sortOptions)) {
+ $this->sortOptions = array('bogus' => true);
+ }
+ }
+
+ /**
+ * Returns the file size, in bytes, or false, on failure
+ *
+ * Files larger than 4GB will show up as being exactly 4GB.
+ *
+ * @param string $filename
+ * @return mixed
+ * @access public
+ */
+ function size($filename)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $result = $this->stat($filename);
+ if ($result === false) {
+ return false;
+ }
+ return isset($result['size']) ? $result['size'] : -1;
+ }
+
+ /**
+ * Save files / directories to cache
+ *
+ * @param string $path
+ * @param mixed $value
+ * @access private
+ */
+ function _update_stat_cache($path, $value)
+ {
+ if ($this->use_stat_cache === false) {
+ return;
+ }
+
+ // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
+ $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
+
+ $temp = &$this->stat_cache;
+ $max = count($dirs) - 1;
+ foreach ($dirs as $i => $dir) {
+ // if $temp is an object that means one of two things.
+ // 1. a file was deleted and changed to a directory behind phpseclib's back
+ // 2. it's a symlink. when lstat is done it's unclear what it's a symlink to
+ if (is_object($temp)) {
+ $temp = array();
+ }
+ if (!isset($temp[$dir])) {
+ $temp[$dir] = array();
+ }
+ if ($i === $max) {
+ if (is_object($temp[$dir]) && is_object($value)) {
+ if (!isset($value->stat) && isset($temp[$dir]->stat)) {
+ $value->stat = $temp[$dir]->stat;
+ }
+ if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
+ $value->lstat = $temp[$dir]->lstat;
+ }
+ }
+ $temp[$dir] = $value;
+ break;
+ }
+ $temp = &$temp[$dir];
+ }
+ }
+
+ /**
+ * Remove files / directories from cache
+ *
+ * @param string $path
+ * @return bool
+ * @access private
+ */
+ function _remove_from_stat_cache($path)
+ {
+ $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
+
+ $temp = &$this->stat_cache;
+ $max = count($dirs) - 1;
+ foreach ($dirs as $i => $dir) {
+ if ($i === $max) {
+ unset($temp[$dir]);
+ return true;
+ }
+ if (!isset($temp[$dir])) {
+ return false;
+ }
+ $temp = &$temp[$dir];
+ }
+ }
+
+ /**
+ * Checks cache for path
+ *
+ * Mainly used by file_exists
+ *
+ * @param string $dir
+ * @return mixed
+ * @access private
+ */
+ function _query_stat_cache($path)
+ {
+ $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
+
+ $temp = &$this->stat_cache;
+ foreach ($dirs as $dir) {
+ if (!isset($temp[$dir])) {
+ return null;
+ }
+ $temp = &$temp[$dir];
+ }
+ return $temp;
+ }
+
+ /**
+ * Returns general information about a file.
+ *
+ * Returns an array on success and false otherwise.
+ *
+ * @param string $filename
+ * @return mixed
+ * @access public
+ */
+ function stat($filename)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $filename = $this->_realpath($filename);
+ if ($filename === false) {
+ return false;
+ }
+
+ if ($this->use_stat_cache) {
+ $result = $this->_query_stat_cache($filename);
+ if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
+ return $result['.']->stat;
+ }
+ if (is_object($result) && isset($result->stat)) {
+ return $result->stat;
+ }
+ }
+
+ $stat = $this->_stat($filename, NET_SFTP_STAT);
+ if ($stat === false) {
+ $this->_remove_from_stat_cache($filename);
+ return false;
+ }
+ if (isset($stat['type'])) {
+ if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
+ $filename.= '/.';
+ }
+ $this->_update_stat_cache($filename, (object) array('stat' => $stat));
+ return $stat;
+ }
+
+ $pwd = $this->pwd;
+ $stat['type'] = $this->chdir($filename) ?
+ NET_SFTP_TYPE_DIRECTORY :
+ NET_SFTP_TYPE_REGULAR;
+ $this->pwd = $pwd;
+
+ if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
+ $filename.= '/.';
+ }
+ $this->_update_stat_cache($filename, (object) array('stat' => $stat));
+
+ return $stat;
+ }
+
+ /**
+ * Returns general information about a file or symbolic link.
+ *
+ * Returns an array on success and false otherwise.
+ *
+ * @param string $filename
+ * @return mixed
+ * @access public
+ */
+ function lstat($filename)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $filename = $this->_realpath($filename);
+ if ($filename === false) {
+ return false;
+ }
+
+ if ($this->use_stat_cache) {
+ $result = $this->_query_stat_cache($filename);
+ if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
+ return $result['.']->lstat;
+ }
+ if (is_object($result) && isset($result->lstat)) {
+ return $result->lstat;
+ }
+ }
+
+ $lstat = $this->_stat($filename, NET_SFTP_LSTAT);
+ if ($lstat === false) {
+ $this->_remove_from_stat_cache($filename);
+ return false;
+ }
+ if (isset($lstat['type'])) {
+ if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
+ $filename.= '/.';
+ }
+ $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
+ return $lstat;
+ }
+
+ $stat = $this->_stat($filename, NET_SFTP_STAT);
+
+ if ($lstat != $stat) {
+ $lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK));
+ $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
+ return $stat;
+ }
+
+ $pwd = $this->pwd;
+ $lstat['type'] = $this->chdir($filename) ?
+ NET_SFTP_TYPE_DIRECTORY :
+ NET_SFTP_TYPE_REGULAR;
+ $this->pwd = $pwd;
+
+ if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
+ $filename.= '/.';
+ }
+ $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
+
+ return $lstat;
+ }
+
+ /**
+ * Returns general information about a file or symbolic link
+ *
+ * Determines information without calling \phpseclib\Net\SFTP::realpath().
+ * The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
+ *
+ * @param string $filename
+ * @param int $type
+ * @return mixed
+ * @access private
+ */
+ function _stat($filename, $type)
+ {
+ // SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
+ $packet = pack('Na*', strlen($filename), $filename);
+ if (!$this->_send_sftp_packet($type, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_ATTRS:
+ return $this->_parseAttributes($response);
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ return false;
+ }
+
+ user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
+ return false;
+ }
+
+ /**
+ * Truncates a file to a given length
+ *
+ * @param string $filename
+ * @param int $new_size
+ * @return bool
+ * @access public
+ */
+ function truncate($filename, $new_size)
+ {
+ $attr = pack('N3', NET_SFTP_ATTR_SIZE, $new_size / 4294967296, $new_size); // 4294967296 == 0x100000000 == 1<<32
+
+ return $this->_setstat($filename, $attr, false);
+ }
+
+ /**
+ * Sets access and modification time of file.
+ *
+ * If the file does not exist, it will be created.
+ *
+ * @param string $filename
+ * @param int $time
+ * @param int $atime
+ * @return bool
+ * @access public
+ */
+ function touch($filename, $time = null, $atime = null)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $filename = $this->_realpath($filename);
+ if ($filename === false) {
+ return false;
+ }
+
+ if (!isset($time)) {
+ $time = time();
+ }
+ if (!isset($atime)) {
+ $atime = $time;
+ }
+
+ $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL;
+ $attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime);
+ $packet = pack('Na*Na*', strlen($filename), $filename, $flags, $attr);
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ return $this->_close_handle(substr($response, 4));
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ break;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+
+ return $this->_setstat($filename, $attr, false);
+ }
+
+ /**
+ * Changes file or directory owner
+ *
+ * Returns true on success or false on error.
+ *
+ * @param string $filename
+ * @param int $uid
+ * @param bool $recursive
+ * @return bool
+ * @access public
+ */
+ function chown($filename, $uid, $recursive = false)
+ {
+ // quoting from <http://www.kernel.org/doc/man-pages/online/pages/man2/chown.2.html>,
+ // "if the owner or group is specified as -1, then that ID is not changed"
+ $attr = pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1);
+
+ return $this->_setstat($filename, $attr, $recursive);
+ }
+
+ /**
+ * Changes file or directory group
+ *
+ * Returns true on success or false on error.
+ *
+ * @param string $filename
+ * @param int $gid
+ * @param bool $recursive
+ * @return bool
+ * @access public
+ */
+ function chgrp($filename, $gid, $recursive = false)
+ {
+ $attr = pack('N3', NET_SFTP_ATTR_UIDGID, -1, $gid);
+
+ return $this->_setstat($filename, $attr, $recursive);
+ }
+
+ /**
+ * Set permissions on a file.
+ *
+ * Returns the new file permissions on success or false on error.
+ * If $recursive is true than this just returns true or false.
+ *
+ * @param int $mode
+ * @param string $filename
+ * @param bool $recursive
+ * @return mixed
+ * @access public
+ */
+ function chmod($mode, $filename, $recursive = false)
+ {
+ if (is_string($mode) && is_int($filename)) {
+ $temp = $mode;
+ $mode = $filename;
+ $filename = $temp;
+ }
+
+ $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
+ if (!$this->_setstat($filename, $attr, $recursive)) {
+ return false;
+ }
+ if ($recursive) {
+ return true;
+ }
+
+ $filename = $this->realpath($filename);
+ // rather than return what the permissions *should* be, we'll return what they actually are. this will also
+ // tell us if the file actually exists.
+ // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
+ $packet = pack('Na*', strlen($filename), $filename);
+ if (!$this->_send_sftp_packet(NET_SFTP_STAT, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_ATTRS:
+ $attrs = $this->_parseAttributes($response);
+ return $attrs['permissions'];
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ return false;
+ }
+
+ user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
+ return false;
+ }
+
+ /**
+ * Sets information about a file
+ *
+ * @param string $filename
+ * @param string $attr
+ * @param bool $recursive
+ * @return bool
+ * @access private
+ */
+ function _setstat($filename, $attr, $recursive)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $filename = $this->_realpath($filename);
+ if ($filename === false) {
+ return false;
+ }
+
+ $this->_remove_from_stat_cache($filename);
+
+ if ($recursive) {
+ $i = 0;
+ $result = $this->_setstat_recursive($filename, $attr, $i);
+ $this->_read_put_responses($i);
+ return $result;
+ }
+
+ // SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to
+ // SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT.
+ if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr))) {
+ return false;
+ }
+
+ /*
+ "Because some systems must use separate system calls to set various attributes, it is possible that a failure
+ response will be returned, but yet some of the attributes may be have been successfully modified. If possible,
+ servers SHOULD avoid this situation; however, clients MUST be aware that this is possible."
+
+ -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
+ */
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Recursively sets information on directories on the SFTP server
+ *
+ * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
+ *
+ * @param string $path
+ * @param string $attr
+ * @param int $i
+ * @return bool
+ * @access private
+ */
+ function _setstat_recursive($path, $attr, &$i)
+ {
+ if (!$this->_read_put_responses($i)) {
+ return false;
+ }
+ $i = 0;
+ $entries = $this->_list($path, true);
+
+ if ($entries === false) {
+ return $this->_setstat($path, $attr, false);
+ }
+
+ // normally $entries would have at least . and .. but it might not if the directories
+ // permissions didn't allow reading
+ if (empty($entries)) {
+ return false;
+ }
+
+ unset($entries['.'], $entries['..']);
+ foreach ($entries as $filename => $props) {
+ if (!isset($props['type'])) {
+ return false;
+ }
+
+ $temp = $path . '/' . $filename;
+ if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
+ if (!$this->_setstat_recursive($temp, $attr, $i)) {
+ return false;
+ }
+ } else {
+ if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($temp), $temp, $attr))) {
+ return false;
+ }
+
+ $i++;
+
+ if ($i >= NET_SFTP_QUEUE_SIZE) {
+ if (!$this->_read_put_responses($i)) {
+ return false;
+ }
+ $i = 0;
+ }
+ }
+ }
+
+ if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($path), $path, $attr))) {
+ return false;
+ }
+
+ $i++;
+
+ if ($i >= NET_SFTP_QUEUE_SIZE) {
+ if (!$this->_read_put_responses($i)) {
+ return false;
+ }
+ $i = 0;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return the target of a symbolic link
+ *
+ * @param string $link
+ * @return mixed
+ * @access public
+ */
+ function readlink($link)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $link = $this->_realpath($link);
+
+ if (!$this->_send_sftp_packet(NET_SFTP_READLINK, pack('Na*', strlen($link), $link))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_NAME:
+ break;
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ return false;
+ default:
+ user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Ncount', $this->_string_shift($response, 4)));
+ // the file isn't a symlink
+ if (!$count) {
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ return $this->_string_shift($response, $length);
+ }
+
+ /**
+ * Create a symlink
+ *
+ * symlink() creates a symbolic link to the existing target with the specified name link.
+ *
+ * @param string $target
+ * @param string $link
+ * @return bool
+ * @access public
+ */
+ function symlink($target, $link)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ //$target = $this->_realpath($target);
+ $link = $this->_realpath($link);
+
+ $packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
+ if (!$this->_send_sftp_packet(NET_SFTP_SYMLINK, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates a directory.
+ *
+ * @param string $dir
+ * @return bool
+ * @access public
+ */
+ function mkdir($dir, $mode = -1, $recursive = false)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $dir = $this->_realpath($dir);
+ // by not providing any permissions, hopefully the server will use the logged in users umask - their
+ // default permissions.
+ $attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
+
+ if ($recursive) {
+ $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));
+ if (empty($dirs[0])) {
+ array_shift($dirs);
+ $dirs[0] = '/' . $dirs[0];
+ }
+ for ($i = 0; $i < count($dirs); $i++) {
+ $temp = array_slice($dirs, 0, $i + 1);
+ $temp = implode('/', $temp);
+ $result = $this->_mkdir_helper($temp, $attr);
+ }
+ return $result;
+ }
+
+ return $this->_mkdir_helper($dir, $attr);
+ }
+
+ /**
+ * Helper function for directory creation
+ *
+ * @param string $dir
+ * @return bool
+ * @access private
+ */
+ function _mkdir_helper($dir, $attr)
+ {
+ if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Removes a directory.
+ *
+ * @param string $dir
+ * @return bool
+ * @access public
+ */
+ function rmdir($dir)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $dir = $this->_realpath($dir);
+ if ($dir === false) {
+ return false;
+ }
+
+ if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($dir), $dir))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
+ $this->_logError($response, $status);
+ return false;
+ }
+
+ $this->_remove_from_stat_cache($dir);
+ // the following will do a soft delete, which would be useful if you deleted a file
+ // and then tried to do a stat on the deleted file. the above, in contrast, does
+ // a hard delete
+ //$this->_update_stat_cache($dir, false);
+
+ return true;
+ }
+
+ /**
+ * Uploads a file to the SFTP server.
+ *
+ * By default, \phpseclib\Net\SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
+ * So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SFTP::get(), you will get a file, twelve bytes
+ * long, containing 'filename.ext' as its contents.
+ *
+ * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
+ * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
+ * large $remote_file will be, as well.
+ *
+ * Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number of bytes to return, and returns a string if there is some data or null if there is no more data
+ *
+ * If $data is a resource then it'll be used as a resource instead.
+ *
+ * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
+ * care of that, yourself.
+ *
+ * $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with
+ * $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following:
+ *
+ * self::SOURCE_LOCAL_FILE | self::RESUME
+ *
+ * If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace
+ * self::RESUME with self::RESUME_START.
+ *
+ * If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed.
+ *
+ * $start and $local_start give you more fine grained control over this process and take precident over self::RESUME
+ * when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle
+ * of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the
+ * middle of one.
+ *
+ * Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE.
+ *
+ * @param string $remote_file
+ * @param string|resource $data
+ * @param int $mode
+ * @param int $start
+ * @param int $local_start
+ * @param callable|null $progressCallback
+ * @return bool
+ * @access public
+ * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
+ */
+ function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $remote_file = $this->_realpath($remote_file);
+ if ($remote_file === false) {
+ return false;
+ }
+
+ $this->_remove_from_stat_cache($remote_file);
+
+ $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE;
+ // according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file."
+ // in practice, it doesn't seem to do that.
+ //$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
+
+ if ($start >= 0) {
+ $offset = $start;
+ } elseif ($mode & self::RESUME) {
+ // if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
+ $size = $this->size($remote_file);
+ $offset = $size !== false ? $size : 0;
+ } else {
+ $offset = 0;
+ $flags|= NET_SFTP_OPEN_TRUNCATE;
+ }
+
+ $packet = pack('Na*N2', strlen($remote_file), $remote_file, $flags, 0);
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ $handle = substr($response, 4);
+ break;
+ case NET_SFTP_STATUS:
+ $this->_logError($response);
+ return false;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
+ $dataCallback = false;
+ switch (true) {
+ case $mode & self::SOURCE_CALLBACK:
+ if (!is_callable($data)) {
+ user_error("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
+ }
+ $dataCallback = $data;
+ // do nothing
+ break;
+ case is_resource($data):
+ $mode = $mode & ~self::SOURCE_LOCAL_FILE;
+ $info = stream_get_meta_data($data);
+ if ($info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') {
+ $fp = fopen('php://memory', 'w+');
+ stream_copy_to_stream($data, $fp);
+ rewind($fp);
+ } else {
+ $fp = $data;
+ }
+ break;
+ case $mode & self::SOURCE_LOCAL_FILE:
+ if (!is_file($data)) {
+ user_error("$data is not a valid file");
+ return false;
+ }
+ $fp = @fopen($data, 'rb');
+ if (!$fp) {
+ return false;
+ }
+ }
+
+ if (isset($fp)) {
+ $stat = fstat($fp);
+ $size = !empty($stat) ? $stat['size'] : 0;
+
+ if ($local_start >= 0) {
+ fseek($fp, $local_start);
+ $size-= $local_start;
+ }
+ } elseif ($dataCallback) {
+ $size = 0;
+ } else {
+ $size = strlen($data);
+ }
+
+ $sent = 0;
+ $size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size;
+
+ $sftp_packet_size = 4096; // PuTTY uses 4096
+ // make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header"
+ $sftp_packet_size-= strlen($handle) + 25;
+ $i = 0;
+ while ($dataCallback || ($size === 0 || $sent < $size)) {
+ if ($dataCallback) {
+ $temp = call_user_func($dataCallback, $sftp_packet_size);
+ if (is_null($temp)) {
+ break;
+ }
+ } else {
+ $temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
+ if ($temp === false || $temp === '') {
+ break;
+ }
+ }
+
+ $subtemp = $offset + $sent;
+ $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
+ if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) {
+ if ($mode & self::SOURCE_LOCAL_FILE) {
+ fclose($fp);
+ }
+ return false;
+ }
+ $sent+= strlen($temp);
+ if (is_callable($progressCallback)) {
+ call_user_func($progressCallback, $sent);
+ }
+
+ $i++;
+
+ if ($i == NET_SFTP_QUEUE_SIZE) {
+ if (!$this->_read_put_responses($i)) {
+ $i = 0;
+ break;
+ }
+ $i = 0;
+ }
+ }
+
+ if (!$this->_read_put_responses($i)) {
+ if ($mode & self::SOURCE_LOCAL_FILE) {
+ fclose($fp);
+ }
+ $this->_close_handle($handle);
+ return false;
+ }
+
+ if ($mode & self::SOURCE_LOCAL_FILE) {
+ fclose($fp);
+ }
+
+ return $this->_close_handle($handle);
+ }
+
+ /**
+ * Reads multiple successive SSH_FXP_WRITE responses
+ *
+ * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i
+ * SSH_FXP_WRITEs, in succession, and then reading $i responses.
+ *
+ * @param int $i
+ * @return bool
+ * @access private
+ */
+ function _read_put_responses($i)
+ {
+ while ($i--) {
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ break;
+ }
+ }
+
+ return $i < 0;
+ }
+
+ /**
+ * Close handle
+ *
+ * @param string $handle
+ * @return bool
+ * @access private
+ */
+ function _close_handle($handle)
+ {
+ if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle))) {
+ return false;
+ }
+
+ // "The client MUST release all resources associated with the handle regardless of the status."
+ // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Downloads a file from the SFTP server.
+ *
+ * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
+ * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
+ * operation.
+ *
+ * $offset and $length can be used to download files in chunks.
+ *
+ * @param string $remote_file
+ * @param string $local_file
+ * @param int $offset
+ * @param int $length
+ * @param callable|null $progressCallback
+ * @return mixed
+ * @access public
+ */
+ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $remote_file = $this->_realpath($remote_file);
+ if ($remote_file === false) {
+ return false;
+ }
+
+ $packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ $handle = substr($response, 4);
+ break;
+ case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
+ $this->_logError($response);
+ return false;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+
+ if (is_resource($local_file)) {
+ $fp = $local_file;
+ $stat = fstat($fp);
+ $res_offset = $stat['size'];
+ } else {
+ $res_offset = 0;
+ if ($local_file !== false) {
+ $fp = fopen($local_file, 'wb');
+ if (!$fp) {
+ return false;
+ }
+ } else {
+ $content = '';
+ }
+ }
+
+ $fclose_check = $local_file !== false && !is_resource($local_file);
+
+ $start = $offset;
+ $read = 0;
+ while (true) {
+ $i = 0;
+
+ while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) {
+ $tempoffset = $start + $read;
+
+ $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
+
+ $packet = pack('Na*N3', strlen($handle), $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
+ if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet, $i)) {
+ if ($fclose_check) {
+ fclose($fp);
+ }
+ return false;
+ }
+ $packet = null;
+ $read+= $packet_size;
+ if (is_callable($progressCallback)) {
+ call_user_func($progressCallback, $read);
+ }
+ $i++;
+ }
+
+ if (!$i) {
+ break;
+ }
+
+ $packets_sent = $i - 1;
+
+ $clear_responses = false;
+ while ($i > 0) {
+ $i--;
+
+ if ($clear_responses) {
+ $this->_get_sftp_packet($packets_sent - $i);
+ continue;
+ } else {
+ $response = $this->_get_sftp_packet($packets_sent - $i);
+ }
+
+ switch ($this->packet_type) {
+ case NET_SFTP_DATA:
+ $temp = substr($response, 4);
+ $offset+= strlen($temp);
+ if ($local_file === false) {
+ $content.= $temp;
+ } else {
+ fputs($fp, $temp);
+ }
+ $temp = null;
+ break;
+ case NET_SFTP_STATUS:
+ // could, in theory, return false if !strlen($content) but we'll hold off for the time being
+ $this->_logError($response);
+ $clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses
+ break;
+ default:
+ if ($fclose_check) {
+ fclose($fp);
+ }
+ user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS');
+ }
+ $response = null;
+ }
+
+ if ($clear_responses) {
+ break;
+ }
+ }
+
+ if ($length > 0 && $length <= $offset - $start) {
+ if ($local_file === false) {
+ $content = substr($content, 0, $length);
+ } else {
+ ftruncate($fp, $length + $res_offset);
+ }
+ }
+
+ if ($fclose_check) {
+ fclose($fp);
+ }
+
+ if (!$this->_close_handle($handle)) {
+ return false;
+ }
+
+ // if $content isn't set that means a file was written to
+ return isset($content) ? $content : true;
+ }
+
+ /**
+ * Deletes a file on the SFTP server.
+ *
+ * @param string $path
+ * @param bool $recursive
+ * @return bool
+ * @access public
+ */
+ function delete($path, $recursive = true)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ if (is_object($path)) {
+ // It's an object. Cast it as string before we check anything else.
+ $path = (string) $path;
+ }
+
+ if (!is_string($path) || $path == '') {
+ return false;
+ }
+
+ $path = $this->_realpath($path);
+ if ($path === false) {
+ return false;
+ }
+
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
+ if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path))) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ if (!$recursive) {
+ return false;
+ }
+ $i = 0;
+ $result = $this->_delete_recursive($path, $i);
+ $this->_read_put_responses($i);
+ return $result;
+ }
+
+ $this->_remove_from_stat_cache($path);
+
+ return true;
+ }
+
+ /**
+ * Recursively deletes directories on the SFTP server
+ *
+ * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
+ *
+ * @param string $path
+ * @param int $i
+ * @return bool
+ * @access private
+ */
+ function _delete_recursive($path, &$i)
+ {
+ if (!$this->_read_put_responses($i)) {
+ return false;
+ }
+ $i = 0;
+ $entries = $this->_list($path, true);
+
+ // normally $entries would have at least . and .. but it might not if the directories
+ // permissions didn't allow reading
+ if (empty($entries)) {
+ return false;
+ }
+
+ unset($entries['.'], $entries['..']);
+ foreach ($entries as $filename => $props) {
+ if (!isset($props['type'])) {
+ return false;
+ }
+
+ $temp = $path . '/' . $filename;
+ if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
+ if (!$this->_delete_recursive($temp, $i)) {
+ return false;
+ }
+ } else {
+ if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) {
+ return false;
+ }
+ $this->_remove_from_stat_cache($temp);
+
+ $i++;
+
+ if ($i >= NET_SFTP_QUEUE_SIZE) {
+ if (!$this->_read_put_responses($i)) {
+ return false;
+ }
+ $i = 0;
+ }
+ }
+ }
+
+ if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) {
+ return false;
+ }
+ $this->_remove_from_stat_cache($path);
+
+ $i++;
+
+ if ($i >= NET_SFTP_QUEUE_SIZE) {
+ if (!$this->_read_put_responses($i)) {
+ return false;
+ }
+ $i = 0;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks whether a file or directory exists
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function file_exists($path)
+ {
+ if ($this->use_stat_cache) {
+ $path = $this->_realpath($path);
+
+ $result = $this->_query_stat_cache($path);
+
+ if (isset($result)) {
+ // return true if $result is an array or if it's an stdClass object
+ return $result !== false;
+ }
+ }
+
+ return $this->stat($path) !== false;
+ }
+
+ /**
+ * Tells whether the filename is a directory
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function is_dir($path)
+ {
+ $result = $this->_get_stat_cache_prop($path, 'type');
+ if ($result === false) {
+ return false;
+ }
+ return $result === NET_SFTP_TYPE_DIRECTORY;
+ }
+
+ /**
+ * Tells whether the filename is a regular file
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function is_file($path)
+ {
+ $result = $this->_get_stat_cache_prop($path, 'type');
+ if ($result === false) {
+ return false;
+ }
+ return $result === NET_SFTP_TYPE_REGULAR;
+ }
+
+ /**
+ * Tells whether the filename is a symbolic link
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function is_link($path)
+ {
+ $result = $this->_get_lstat_cache_prop($path, 'type');
+ if ($result === false) {
+ return false;
+ }
+ return $result === NET_SFTP_TYPE_SYMLINK;
+ }
+
+ /**
+ * Tells whether a file exists and is readable
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function is_readable($path)
+ {
+ $path = $this->_realpath($path);
+
+ $packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_READ, 0);
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ return true;
+ case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
+ return false;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+ }
+
+ /**
+ * Tells whether the filename is writable
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function is_writable($path)
+ {
+ $path = $this->_realpath($path);
+
+ $packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_WRITE, 0);
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ switch ($this->packet_type) {
+ case NET_SFTP_HANDLE:
+ return true;
+ case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
+ return false;
+ default:
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
+ return false;
+ }
+ }
+
+ /**
+ * Tells whether the filename is writeable
+ *
+ * Alias of is_writable
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function is_writeable($path)
+ {
+ return $this->is_writable($path);
+ }
+
+ /**
+ * Gets last access time of file
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function fileatime($path)
+ {
+ return $this->_get_stat_cache_prop($path, 'atime');
+ }
+
+ /**
+ * Gets file modification time
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function filemtime($path)
+ {
+ return $this->_get_stat_cache_prop($path, 'mtime');
+ }
+
+ /**
+ * Gets file permissions
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function fileperms($path)
+ {
+ return $this->_get_stat_cache_prop($path, 'permissions');
+ }
+
+ /**
+ * Gets file owner
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function fileowner($path)
+ {
+ return $this->_get_stat_cache_prop($path, 'uid');
+ }
+
+ /**
+ * Gets file group
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function filegroup($path)
+ {
+ return $this->_get_stat_cache_prop($path, 'gid');
+ }
+
+ /**
+ * Gets file size
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function filesize($path)
+ {
+ return $this->_get_stat_cache_prop($path, 'size');
+ }
+
+ /**
+ * Gets file type
+ *
+ * @param string $path
+ * @return mixed
+ * @access public
+ */
+ function filetype($path)
+ {
+ $type = $this->_get_stat_cache_prop($path, 'type');
+ if ($type === false) {
+ return false;
+ }
+
+ switch ($type) {
+ case NET_SFTP_TYPE_BLOCK_DEVICE:
+ return 'block';
+ case NET_SFTP_TYPE_CHAR_DEVICE:
+ return 'char';
+ case NET_SFTP_TYPE_DIRECTORY:
+ return 'dir';
+ case NET_SFTP_TYPE_FIFO:
+ return 'fifo';
+ case NET_SFTP_TYPE_REGULAR:
+ return 'file';
+ case NET_SFTP_TYPE_SYMLINK:
+ return 'link';
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Return a stat properity
+ *
+ * Uses cache if appropriate.
+ *
+ * @param string $path
+ * @param string $prop
+ * @return mixed
+ * @access private
+ */
+ function _get_stat_cache_prop($path, $prop)
+ {
+ return $this->_get_xstat_cache_prop($path, $prop, 'stat');
+ }
+
+ /**
+ * Return an lstat properity
+ *
+ * Uses cache if appropriate.
+ *
+ * @param string $path
+ * @param string $prop
+ * @return mixed
+ * @access private
+ */
+ function _get_lstat_cache_prop($path, $prop)
+ {
+ return $this->_get_xstat_cache_prop($path, $prop, 'lstat');
+ }
+
+ /**
+ * Return a stat or lstat properity
+ *
+ * Uses cache if appropriate.
+ *
+ * @param string $path
+ * @param string $prop
+ * @return mixed
+ * @access private
+ */
+ function _get_xstat_cache_prop($path, $prop, $type)
+ {
+ if ($this->use_stat_cache) {
+ $path = $this->_realpath($path);
+
+ $result = $this->_query_stat_cache($path);
+
+ if (is_object($result) && isset($result->$type)) {
+ return $result->{$type}[$prop];
+ }
+ }
+
+ $result = $this->$type($path);
+
+ if ($result === false || !isset($result[$prop])) {
+ return false;
+ }
+
+ return $result[$prop];
+ }
+
+ /**
+ * Renames a file or a directory on the SFTP server
+ *
+ * @param string $oldname
+ * @param string $newname
+ * @return bool
+ * @access public
+ */
+ function rename($oldname, $newname)
+ {
+ if (!($this->bitmap & SSH2::MASK_LOGIN)) {
+ return false;
+ }
+
+ $oldname = $this->_realpath($oldname);
+ $newname = $this->_realpath($newname);
+ if ($oldname === false || $newname === false) {
+ return false;
+ }
+
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
+ $packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname);
+ if (!$this->_send_sftp_packet(NET_SFTP_RENAME, $packet)) {
+ return false;
+ }
+
+ $response = $this->_get_sftp_packet();
+ if ($this->packet_type != NET_SFTP_STATUS) {
+ user_error('Expected SSH_FXP_STATUS');
+ return false;
+ }
+
+ // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nstatus', $this->_string_shift($response, 4)));
+ if ($status != NET_SFTP_STATUS_OK) {
+ $this->_logError($response, $status);
+ return false;
+ }
+
+ // don't move the stat cache entry over since this operation could very well change the
+ // atime and mtime attributes
+ //$this->_update_stat_cache($newname, $this->_query_stat_cache($oldname));
+ $this->_remove_from_stat_cache($oldname);
+ $this->_remove_from_stat_cache($newname);
+
+ return true;
+ }
+
+ /**
+ * Parse Attributes
+ *
+ * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
+ *
+ * @param string $response
+ * @return array
+ * @access private
+ */
+ function _parseAttributes(&$response)
+ {
+ $attr = array();
+ if (strlen($response) < 4) {
+ user_error('Malformed file attributes');
+ return array();
+ }
+ extract(unpack('Nflags', $this->_string_shift($response, 4)));
+ // SFTPv4+ have a type field (a byte) that follows the above flag field
+ foreach ($this->attributes as $key => $value) {
+ switch ($flags & $key) {
+ case NET_SFTP_ATTR_SIZE: // 0x00000001
+ // The size attribute is defined as an unsigned 64-bit integer.
+ // The following will use floats on 32-bit platforms, if necessary.
+ // As can be seen in the BigInteger class, floats are generally
+ // IEEE 754 binary64 "double precision" on such platforms and
+ // as such can represent integers of at least 2^50 without loss
+ // of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
+ $attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
+ break;
+ case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
+ if (strlen($response) < 8) {
+ user_error('Malformed file attributes');
+ return $attr;
+ }
+ $attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
+ break;
+ case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
+ if (strlen($response) < 4) {
+ user_error('Malformed file attributes');
+ return $attr;
+ }
+ $attr+= unpack('Npermissions', $this->_string_shift($response, 4));
+ // mode == permissions; permissions was the original array key and is retained for bc purposes.
+ // mode was added because that's the more industry standard terminology
+ $attr+= array('mode' => $attr['permissions']);
+ $fileType = $this->_parseMode($attr['permissions']);
+ if ($fileType !== false) {
+ $attr+= array('type' => $fileType);
+ }
+ break;
+ case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
+ if (strlen($response) < 8) {
+ user_error('Malformed file attributes');
+ return $attr;
+ }
+ $attr+= unpack('Natime/Nmtime', $this->_string_shift($response, 8));
+ break;
+ case NET_SFTP_ATTR_EXTENDED: // 0x80000000
+ if (strlen($response) < 4) {
+ user_error('Malformed file attributes');
+ return $attr;
+ }
+ extract(unpack('Ncount', $this->_string_shift($response, 4)));
+ for ($i = 0; $i < $count; $i++) {
+ if (strlen($response) < 4) {
+ user_error('Malformed file attributes');
+ return $attr;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $key = $this->_string_shift($response, $length);
+ if (strlen($response) < 4) {
+ user_error('Malformed file attributes');
+ return $attr;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $attr[$key] = $this->_string_shift($response, $length);
+ }
+ }
+ }
+ return $attr;
+ }
+
+ /**
+ * Attempt to identify the file type
+ *
+ * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway
+ *
+ * @param int $mode
+ * @return int
+ * @access private
+ */
+ function _parseMode($mode)
+ {
+ // values come from http://lxr.free-electrons.com/source/include/uapi/linux/stat.h#L12
+ // see, also, http://linux.die.net/man/2/stat
+ switch ($mode & 0170000) {// ie. 1111 0000 0000 0000
+ case 0000000: // no file type specified - figure out the file type using alternative means
+ return false;
+ case 0040000:
+ return NET_SFTP_TYPE_DIRECTORY;
+ case 0100000:
+ return NET_SFTP_TYPE_REGULAR;
+ case 0120000:
+ return NET_SFTP_TYPE_SYMLINK;
+ // new types introduced in SFTPv5+
+ // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
+ case 0010000: // named pipe (fifo)
+ return NET_SFTP_TYPE_FIFO;
+ case 0020000: // character special
+ return NET_SFTP_TYPE_CHAR_DEVICE;
+ case 0060000: // block special
+ return NET_SFTP_TYPE_BLOCK_DEVICE;
+ case 0140000: // socket
+ return NET_SFTP_TYPE_SOCKET;
+ case 0160000: // whiteout
+ // "SPECIAL should be used for files that are of
+ // a known type which cannot be expressed in the protocol"
+ return NET_SFTP_TYPE_SPECIAL;
+ default:
+ return NET_SFTP_TYPE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Parse Longname
+ *
+ * SFTPv3 doesn't provide any easy way of identifying a file type. You could try to open
+ * a file as a directory and see if an error is returned or you could try to parse the
+ * SFTPv3-specific longname field of the SSH_FXP_NAME packet. That's what this function does.
+ * The result is returned using the
+ * {@link http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 SFTPv4 type constants}.
+ *
+ * If the longname is in an unrecognized format bool(false) is returned.
+ *
+ * @param string $longname
+ * @return mixed
+ * @access private
+ */
+ function _parseLongname($longname)
+ {
+ // http://en.wikipedia.org/wiki/Unix_file_types
+ // http://en.wikipedia.org/wiki/Filesystem_permissions#Notation_of_traditional_Unix_permissions
+ if (preg_match('#^[^/]([r-][w-][xstST-]){3}#', $longname)) {
+ switch ($longname[0]) {
+ case '-':
+ return NET_SFTP_TYPE_REGULAR;
+ case 'd':
+ return NET_SFTP_TYPE_DIRECTORY;
+ case 'l':
+ return NET_SFTP_TYPE_SYMLINK;
+ default:
+ return NET_SFTP_TYPE_SPECIAL;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Sends SFTP Packets
+ *
+ * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
+ *
+ * @param int $type
+ * @param string $data
+ * @see self::_get_sftp_packet()
+ * @see self::_send_channel_packet()
+ * @return bool
+ * @access private
+ */
+ function _send_sftp_packet($type, $data, $request_id = 1)
+ {
+ $packet = $this->use_request_id ?
+ pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) :
+ pack('NCa*', strlen($data) + 1, $type, $data);
+
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
+ $result = $this->_send_channel_packet(self::CHANNEL, $packet);
+ $stop = strtok(microtime(), ' ') + strtok('');
+
+ if (defined('NET_SFTP_LOGGING')) {
+ $packet_type = '-> ' . $this->packet_types[$type] .
+ ' (' . round($stop - $start, 4) . 's)';
+ if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
+ echo "<pre>\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n</pre>\r\n";
+ flush();
+ ob_flush();
+ } else {
+ $this->packet_type_log[] = $packet_type;
+ if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
+ $this->packet_log[] = $data;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Receives SFTP Packets
+ *
+ * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
+ *
+ * Incidentally, the number of SSH_MSG_CHANNEL_DATA messages has no bearing on the number of SFTP packets present.
+ * There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA
+ * messages containing one SFTP packet.
+ *
+ * @see self::_send_sftp_packet()
+ * @return string
+ * @access private
+ */
+ function _get_sftp_packet($request_id = null)
+ {
+ if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
+ $this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
+ $temp = $this->requestBuffer[$request_id]['packet'];
+ unset($this->requestBuffer[$request_id]);
+ return $temp;
+ }
+
+ // in SSH2.php the timeout is cumulative per function call. eg. exec() will
+ // timeout after 10s. but for SFTP.php it's cumulative per packet
+ $this->curTimeout = $this->timeout;
+
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
+
+ // SFTP packet length
+ while (strlen($this->packet_buffer) < 4) {
+ $temp = $this->_get_channel_packet(self::CHANNEL, true);
+ if (is_bool($temp)) {
+ $this->packet_type = false;
+ $this->packet_buffer = '';
+ return false;
+ }
+ $this->packet_buffer.= $temp;
+ }
+ if (strlen($this->packet_buffer) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($this->packet_buffer, 4)));
+ $tempLength = $length;
+ $tempLength-= strlen($this->packet_buffer);
+
+
+ // 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h
+ if ($tempLength > 256 * 1024) {
+ user_error('Invalid SFTP packet size');
+ return false;
+ }
+
+ // SFTP packet type and data payload
+ while ($tempLength > 0) {
+ $temp = $this->_get_channel_packet(self::CHANNEL, true);
+ if (is_bool($temp)) {
+ $this->packet_type = false;
+ $this->packet_buffer = '';
+ return false;
+ }
+ $this->packet_buffer.= $temp;
+ $tempLength-= strlen($temp);
+ }
+
+ $stop = strtok(microtime(), ' ') + strtok('');
+
+ $this->packet_type = ord($this->_string_shift($this->packet_buffer));
+
+ if ($this->use_request_id) {
+ extract(unpack('Npacket_id', $this->_string_shift($this->packet_buffer, 4))); // remove the request id
+ $length-= 5; // account for the request id and the packet type
+ } else {
+ $length-= 1; // account for the packet type
+ }
+
+ $packet = $this->_string_shift($this->packet_buffer, $length);
+
+ if (defined('NET_SFTP_LOGGING')) {
+ $packet_type = '<- ' . $this->packet_types[$this->packet_type] .
+ ' (' . round($stop - $start, 4) . 's)';
+ if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
+ echo "<pre>\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n</pre>\r\n";
+ flush();
+ ob_flush();
+ } else {
+ $this->packet_type_log[] = $packet_type;
+ if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
+ $this->packet_log[] = $packet;
+ }
+ }
+ }
+
+ if (isset($request_id) && $this->use_request_id && $packet_id != $request_id) {
+ $this->requestBuffer[$packet_id] = array(
+ 'packet_type' => $this->packet_type,
+ 'packet' => $packet
+ );
+ return $this->_get_sftp_packet($request_id);
+ }
+
+ return $packet;
+ }
+
+ /**
+ * Returns a log of the packets that have been sent and received.
+ *
+ * Returns a string if NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX, an array if NET_SFTP_LOGGING == NET_SFTP_LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
+ *
+ * @access public
+ * @return string or Array
+ */
+ function getSFTPLog()
+ {
+ if (!defined('NET_SFTP_LOGGING')) {
+ return false;
+ }
+
+ switch (NET_SFTP_LOGGING) {
+ case self::LOG_COMPLEX:
+ return $this->_format_log($this->packet_log, $this->packet_type_log);
+ break;
+ //case self::LOG_SIMPLE:
+ default:
+ return $this->packet_type_log;
+ }
+ }
+
+ /**
+ * Returns all errors
+ *
+ * @return array
+ * @access public
+ */
+ function getSFTPErrors()
+ {
+ return $this->sftp_errors;
+ }
+
+ /**
+ * Returns the last error
+ *
+ * @return string
+ * @access public
+ */
+ function getLastSFTPError()
+ {
+ return count($this->sftp_errors) ? $this->sftp_errors[count($this->sftp_errors) - 1] : '';
+ }
+
+ /**
+ * Get supported SFTP versions
+ *
+ * @return array
+ * @access public
+ */
+ function getSupportedVersions()
+ {
+ $temp = array('version' => $this->version);
+ if (isset($this->extensions['versions'])) {
+ $temp['extensions'] = $this->extensions['versions'];
+ }
+ return $temp;
+ }
+
+ /**
+ * Disconnect
+ *
+ * @param int $reason
+ * @return bool
+ * @access private
+ */
+ function _disconnect($reason)
+ {
+ $this->pwd = false;
+ parent::_disconnect($reason);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * SFTP Stream Wrapper
+ *
+ * Creates an sftp:// protocol handler that can be used with, for example, fopen(), dir(), etc.
+ *
+ * PHP version 5
+ *
+ * @category Net
+ * @package SFTP
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2013 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Net\SFTP;
+
+use phpseclib\Crypt\RSA;
+use phpseclib\Net\SFTP;
+
+/**
+ * SFTP Stream Wrapper
+ *
+ * @package SFTP
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class Stream
+{
+ /**
+ * SFTP instances
+ *
+ * Rather than re-create the connection we re-use instances if possible
+ *
+ * @var array
+ */
+ static $instances;
+
+ /**
+ * SFTP instance
+ *
+ * @var object
+ * @access private
+ */
+ var $sftp;
+
+ /**
+ * Path
+ *
+ * @var string
+ * @access private
+ */
+ var $path;
+
+ /**
+ * Mode
+ *
+ * @var string
+ * @access private
+ */
+ var $mode;
+
+ /**
+ * Position
+ *
+ * @var int
+ * @access private
+ */
+ var $pos;
+
+ /**
+ * Size
+ *
+ * @var int
+ * @access private
+ */
+ var $size;
+
+ /**
+ * Directory entries
+ *
+ * @var array
+ * @access private
+ */
+ var $entries;
+
+ /**
+ * EOF flag
+ *
+ * @var bool
+ * @access private
+ */
+ var $eof;
+
+ /**
+ * Context resource
+ *
+ * Technically this needs to be publically accessible so PHP can set it directly
+ *
+ * @var resource
+ * @access public
+ */
+ var $context;
+
+ /**
+ * Notification callback function
+ *
+ * @var callable
+ * @access public
+ */
+ var $notification;
+
+ /**
+ * Registers this class as a URL wrapper.
+ *
+ * @param string $protocol The wrapper name to be registered.
+ * @return bool True on success, false otherwise.
+ * @access public
+ */
+ static function register($protocol = 'sftp')
+ {
+ if (in_array($protocol, stream_get_wrappers(), true)) {
+ return false;
+ }
+ return stream_wrapper_register($protocol, get_called_class());
+ }
+
+ /**
+ * The Constructor
+ *
+ * @access public
+ */
+ function __construct()
+ {
+ if (defined('NET_SFTP_STREAM_LOGGING')) {
+ echo "__construct()\r\n";
+ }
+ }
+
+ /**
+ * Path Parser
+ *
+ * Extract a path from a URI and actually connect to an SSH server if appropriate
+ *
+ * If "notification" is set as a context parameter the message code for successful login is
+ * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
+ *
+ * @param string $path
+ * @return string
+ * @access private
+ */
+ function _parse_path($path)
+ {
+ $orig = $path;
+ extract(parse_url($path) + array('port' => 22));
+ if (isset($query)) {
+ $path.= '?' . $query;
+ } elseif (preg_match('/(\?|\?#)$/', $orig)) {
+ $path.= '?';
+ }
+ if (isset($fragment)) {
+ $path.= '#' . $fragment;
+ } elseif ($orig[strlen($orig) - 1] == '#') {
+ $path.= '#';
+ }
+
+ if (!isset($host)) {
+ return false;
+ }
+
+ if (isset($this->context)) {
+ $context = stream_context_get_params($this->context);
+ if (isset($context['notification'])) {
+ $this->notification = $context['notification'];
+ }
+ }
+
+ if ($host[0] == '$') {
+ $host = substr($host, 1);
+ global ${$host};
+ if (($$host instanceof SFTP) === false) {
+ return false;
+ }
+ $this->sftp = $$host;
+ } else {
+ if (isset($this->context)) {
+ $context = stream_context_get_options($this->context);
+ }
+ if (isset($context[$scheme]['session'])) {
+ $sftp = $context[$scheme]['session'];
+ }
+ if (isset($context[$scheme]['sftp'])) {
+ $sftp = $context[$scheme]['sftp'];
+ }
+ if (isset($sftp) && $sftp instanceof SFTP) {
+ $this->sftp = $sftp;
+ return $path;
+ }
+ if (isset($context[$scheme]['username'])) {
+ $user = $context[$scheme]['username'];
+ }
+ if (isset($context[$scheme]['password'])) {
+ $pass = $context[$scheme]['password'];
+ }
+ if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof RSA) {
+ $pass = $context[$scheme]['privkey'];
+ }
+
+ if (!isset($user) || !isset($pass)) {
+ return false;
+ }
+
+ // casting $pass to a string is necessary in the event that it's a \phpseclib\Crypt\RSA object
+ if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
+ $this->sftp = self::$instances[$host][$port][$user][(string) $pass];
+ } else {
+ $this->sftp = new SFTP($host, $port);
+ $this->sftp->disableStatCache();
+ if (isset($this->notification) && is_callable($this->notification)) {
+ /* if !is_callable($this->notification) we could do this:
+
+ user_error('fopen(): failed to call user notifier', E_USER_WARNING);
+
+ the ftp wrapper gives errors like that when the notifier isn't callable.
+ i've opted not to do that, however, since the ftp wrapper gives the line
+ on which the fopen occurred as the line number - not the line that the
+ user_error is on.
+ */
+ call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
+ call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
+ if (!$this->sftp->login($user, $pass)) {
+ call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
+ return false;
+ }
+ call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
+ } else {
+ if (!$this->sftp->login($user, $pass)) {
+ return false;
+ }
+ }
+ self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
+ }
+ }
+
+ return $path;
+ }
+
+ /**
+ * Opens file or URL
+ *
+ * @param string $path
+ * @param string $mode
+ * @param int $options
+ * @param string $opened_path
+ * @return bool
+ * @access public
+ */
+ function _stream_open($path, $mode, $options, &$opened_path)
+ {
+ $path = $this->_parse_path($path);
+
+ if ($path === false) {
+ return false;
+ }
+ $this->path = $path;
+
+ $this->size = $this->sftp->size($path);
+ $this->mode = preg_replace('#[bt]$#', '', $mode);
+ $this->eof = false;
+
+ if ($this->size === false) {
+ if ($this->mode[0] == 'r') {
+ return false;
+ } else {
+ $this->sftp->touch($path);
+ $this->size = 0;
+ }
+ } else {
+ switch ($this->mode[0]) {
+ case 'x':
+ return false;
+ case 'w':
+ $this->sftp->truncate($path, 0);
+ $this->size = 0;
+ }
+ }
+
+ $this->pos = $this->mode[0] != 'a' ? 0 : $this->size;
+
+ return true;
+ }
+
+ /**
+ * Read from stream
+ *
+ * @param int $count
+ * @return mixed
+ * @access public
+ */
+ function _stream_read($count)
+ {
+ switch ($this->mode) {
+ case 'w':
+ case 'a':
+ case 'x':
+ case 'c':
+ return false;
+ }
+
+ // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite
+ //if ($this->pos >= $this->size) {
+ // $this->eof = true;
+ // return false;
+ //}
+
+ $result = $this->sftp->get($this->path, false, $this->pos, $count);
+ if (isset($this->notification) && is_callable($this->notification)) {
+ if ($result === false) {
+ call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
+ return 0;
+ }
+ // seems that PHP calls stream_read in 8k chunks
+ call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size);
+ }
+
+ if (empty($result)) { // ie. false or empty string
+ $this->eof = true;
+ return false;
+ }
+ $this->pos+= strlen($result);
+
+ return $result;
+ }
+
+ /**
+ * Write to stream
+ *
+ * @param string $data
+ * @return mixed
+ * @access public
+ */
+ function _stream_write($data)
+ {
+ switch ($this->mode) {
+ case 'r':
+ return false;
+ }
+
+ $result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos);
+ if (isset($this->notification) && is_callable($this->notification)) {
+ if (!$result) {
+ call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
+ return 0;
+ }
+ // seems that PHP splits up strings into 8k blocks before calling stream_write
+ call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
+ }
+
+ if ($result === false) {
+ return false;
+ }
+ $this->pos+= strlen($data);
+ if ($this->pos > $this->size) {
+ $this->size = $this->pos;
+ }
+ $this->eof = false;
+ return strlen($data);
+ }
+
+ /**
+ * Retrieve the current position of a stream
+ *
+ * @return int
+ * @access public
+ */
+ function _stream_tell()
+ {
+ return $this->pos;
+ }
+
+ /**
+ * Tests for end-of-file on a file pointer
+ *
+ * In my testing there are four classes functions that normally effect the pointer:
+ * fseek, fputs / fwrite, fgets / fread and ftruncate.
+ *
+ * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof()
+ * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
+ * will return false. do fread($fp, 1) and feof() will then return true.
+ *
+ * @return bool
+ * @access public
+ */
+ function _stream_eof()
+ {
+ return $this->eof;
+ }
+
+ /**
+ * Seeks to specific location in a stream
+ *
+ * @param int $offset
+ * @param int $whence
+ * @return bool
+ * @access public
+ */
+ function _stream_seek($offset, $whence)
+ {
+ switch ($whence) {
+ case SEEK_SET:
+ if ($offset >= $this->size || $offset < 0) {
+ return false;
+ }
+ break;
+ case SEEK_CUR:
+ $offset+= $this->pos;
+ break;
+ case SEEK_END:
+ $offset+= $this->size;
+ }
+
+ $this->pos = $offset;
+ $this->eof = false;
+ return true;
+ }
+
+ /**
+ * Change stream options
+ *
+ * @param string $path
+ * @param int $option
+ * @param mixed $var
+ * @return bool
+ * @access public
+ */
+ function _stream_metadata($path, $option, $var)
+ {
+ $path = $this->_parse_path($path);
+ if ($path === false) {
+ return false;
+ }
+
+ // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined
+ // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246
+ // and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
+ switch ($option) {
+ case 1: // PHP_STREAM_META_TOUCH
+ return $this->sftp->touch($path, $var[0], $var[1]);
+ case 2: // PHP_STREAM_OWNER_NAME
+ case 3: // PHP_STREAM_GROUP_NAME
+ return false;
+ case 4: // PHP_STREAM_META_OWNER
+ return $this->sftp->chown($path, $var);
+ case 5: // PHP_STREAM_META_GROUP
+ return $this->sftp->chgrp($path, $var);
+ case 6: // PHP_STREAM_META_ACCESS
+ return $this->sftp->chmod($path, $var) !== false;
+ }
+ }
+
+ /**
+ * Retrieve the underlaying resource
+ *
+ * @param int $cast_as
+ * @return resource
+ * @access public
+ */
+ function _stream_cast($cast_as)
+ {
+ return $this->sftp->fsock;
+ }
+
+ /**
+ * Advisory file locking
+ *
+ * @param int $operation
+ * @return bool
+ * @access public
+ */
+ function _stream_lock($operation)
+ {
+ return false;
+ }
+
+ /**
+ * Renames a file or directory
+ *
+ * Attempts to rename oldname to newname, moving it between directories if necessary.
+ * If newname exists, it will be overwritten. This is a departure from what \phpseclib\Net\SFTP
+ * does.
+ *
+ * @param string $path_from
+ * @param string $path_to
+ * @return bool
+ * @access public
+ */
+ function _rename($path_from, $path_to)
+ {
+ $path1 = parse_url($path_from);
+ $path2 = parse_url($path_to);
+ unset($path1['path'], $path2['path']);
+ if ($path1 != $path2) {
+ return false;
+ }
+
+ $path_from = $this->_parse_path($path_from);
+ $path_to = parse_url($path_to);
+ if ($path_from === false) {
+ return false;
+ }
+
+ $path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2
+ // "It is an error if there already exists a file with the name specified by newpath."
+ // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5
+ if (!$this->sftp->rename($path_from, $path_to)) {
+ if ($this->sftp->stat($path_to)) {
+ return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Open directory handle
+ *
+ * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
+ * removed in 5.4 I'm just going to ignore it.
+ *
+ * Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client
+ * sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting
+ * the SFTP specs:
+ *
+ * The SSH_FXP_NAME response has the following format:
+ *
+ * uint32 id
+ * uint32 count
+ * repeats count times:
+ * string filename
+ * string longname
+ * ATTRS attrs
+ *
+ * @param string $path
+ * @param int $options
+ * @return bool
+ * @access public
+ */
+ function _dir_opendir($path, $options)
+ {
+ $path = $this->_parse_path($path);
+ if ($path === false) {
+ return false;
+ }
+ $this->pos = 0;
+ $this->entries = $this->sftp->nlist($path);
+ return $this->entries !== false;
+ }
+
+ /**
+ * Read entry from directory handle
+ *
+ * @return mixed
+ * @access public
+ */
+ function _dir_readdir()
+ {
+ if (isset($this->entries[$this->pos])) {
+ return $this->entries[$this->pos++];
+ }
+ return false;
+ }
+
+ /**
+ * Rewind directory handle
+ *
+ * @return bool
+ * @access public
+ */
+ function _dir_rewinddir()
+ {
+ $this->pos = 0;
+ return true;
+ }
+
+ /**
+ * Close directory handle
+ *
+ * @return bool
+ * @access public
+ */
+ function _dir_closedir()
+ {
+ return true;
+ }
+
+ /**
+ * Create a directory
+ *
+ * Only valid $options is STREAM_MKDIR_RECURSIVE
+ *
+ * @param string $path
+ * @param int $mode
+ * @param int $options
+ * @return bool
+ * @access public
+ */
+ function _mkdir($path, $mode, $options)
+ {
+ $path = $this->_parse_path($path);
+ if ($path === false) {
+ return false;
+ }
+
+ return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE);
+ }
+
+ /**
+ * Removes a directory
+ *
+ * Only valid $options is STREAM_MKDIR_RECURSIVE per <http://php.net/streamwrapper.rmdir>, however,
+ * <http://php.net/rmdir> does not have a $recursive parameter as mkdir() does so I don't know how
+ * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
+ * $options. What does 8 correspond to?
+ *
+ * @param string $path
+ * @param int $mode
+ * @param int $options
+ * @return bool
+ * @access public
+ */
+ function _rmdir($path, $options)
+ {
+ $path = $this->_parse_path($path);
+ if ($path === false) {
+ return false;
+ }
+
+ return $this->sftp->rmdir($path);
+ }
+
+ /**
+ * Flushes the output
+ *
+ * See <http://php.net/fflush>. Always returns true because \phpseclib\Net\SFTP doesn't cache stuff before writing
+ *
+ * @return bool
+ * @access public
+ */
+ function _stream_flush()
+ {
+ return true;
+ }
+
+ /**
+ * Retrieve information about a file resource
+ *
+ * @return mixed
+ * @access public
+ */
+ function _stream_stat()
+ {
+ $results = $this->sftp->stat($this->path);
+ if ($results === false) {
+ return false;
+ }
+ return $results;
+ }
+
+ /**
+ * Delete a file
+ *
+ * @param string $path
+ * @return bool
+ * @access public
+ */
+ function _unlink($path)
+ {
+ $path = $this->_parse_path($path);
+ if ($path === false) {
+ return false;
+ }
+
+ return $this->sftp->delete($path, false);
+ }
+
+ /**
+ * Retrieve information about a file
+ *
+ * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib\Net\SFTP\Stream is quiet by default
+ * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
+ * cross that bridge when and if it's reached
+ *
+ * @param string $path
+ * @param int $flags
+ * @return mixed
+ * @access public
+ */
+ function _url_stat($path, $flags)
+ {
+ $path = $this->_parse_path($path);
+ if ($path === false) {
+ return false;
+ }
+
+ $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path);
+ if ($results === false) {
+ return false;
+ }
+
+ return $results;
+ }
+
+ /**
+ * Truncate stream
+ *
+ * @param int $new_size
+ * @return bool
+ * @access public
+ */
+ function _stream_truncate($new_size)
+ {
+ if (!$this->sftp->truncate($this->path, $new_size)) {
+ return false;
+ }
+
+ $this->eof = false;
+ $this->size = $new_size;
+
+ return true;
+ }
+
+ /**
+ * Change stream options
+ *
+ * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
+ * The other two aren't supported because of limitations in \phpseclib\Net\SFTP.
+ *
+ * @param int $option
+ * @param int $arg1
+ * @param int $arg2
+ * @return bool
+ * @access public
+ */
+ function _stream_set_option($option, $arg1, $arg2)
+ {
+ return false;
+ }
+
+ /**
+ * Close an resource
+ *
+ * @access public
+ */
+ function _stream_close()
+ {
+ }
+
+ /**
+ * __call Magic Method
+ *
+ * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
+ * Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
+ * lets you figure that out.
+ *
+ * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
+ * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
+ *
+ * @param string
+ * @param array
+ * @return mixed
+ * @access public
+ */
+ function __call($name, $arguments)
+ {
+ if (defined('NET_SFTP_STREAM_LOGGING')) {
+ echo $name . '(';
+ $last = count($arguments) - 1;
+ foreach ($arguments as $i => $argument) {
+ var_export($argument);
+ if ($i != $last) {
+ echo ',';
+ }
+ }
+ echo ")\r\n";
+ }
+ $name = '_' . $name;
+ if (!method_exists($this, $name)) {
+ return false;
+ }
+ return call_user_func_array(array($this, $name), $arguments);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of SSHv1.
+ *
+ * PHP version 5
+ *
+ * Here's a short example of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $ssh = new \phpseclib\Net\SSH1('www.domain.tld');
+ * if (!$ssh->login('username', 'password')) {
+ * exit('Login Failed');
+ * }
+ *
+ * echo $ssh->exec('ls -la');
+ * ?>
+ * </code>
+ *
+ * Here's another short example:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $ssh = new \phpseclib\Net\SSH1('www.domain.tld');
+ * if (!$ssh->login('username', 'password')) {
+ * exit('Login Failed');
+ * }
+ *
+ * echo $ssh->read('username@username:~$');
+ * $ssh->write("ls -la\n");
+ * echo $ssh->read('username@username:~$');
+ * ?>
+ * </code>
+ *
+ * More information on the SSHv1 specification can be found by reading
+ * {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}.
+ *
+ * @category Net
+ * @package SSH1
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Net;
+
+use phpseclib\Crypt\DES;
+use phpseclib\Crypt\Random;
+use phpseclib\Crypt\TripleDES;
+use phpseclib\Math\BigInteger;
+
+/**
+ * Pure-PHP implementation of SSHv1.
+ *
+ * @package SSH1
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class SSH1
+{
+ /**#@+
+ * Encryption Methods
+ *
+ * @see \phpseclib\Net\SSH1::getSupportedCiphers()
+ * @access public
+ */
+ /**
+ * No encryption
+ *
+ * Not supported.
+ */
+ const CIPHER_NONE = 0;
+ /**
+ * IDEA in CFB mode
+ *
+ * Not supported.
+ */
+ const CIPHER_IDEA = 1;
+ /**
+ * DES in CBC mode
+ */
+ const CIPHER_DES = 2;
+ /**
+ * Triple-DES in CBC mode
+ *
+ * All implementations are required to support this
+ */
+ const CIPHER_3DES = 3;
+ /**
+ * TRI's Simple Stream encryption CBC
+ *
+ * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h),
+ * although it doesn't use it (see cipher.c)
+ */
+ const CIPHER_BROKEN_TSS = 4;
+ /**
+ * RC4
+ *
+ * Not supported.
+ *
+ * @internal According to the SSH1 specs:
+ *
+ * "The first 16 bytes of the session key are used as the key for
+ * the server to client direction. The remaining 16 bytes are used
+ * as the key for the client to server direction. This gives
+ * independent 128-bit keys for each direction."
+ *
+ * This library currently only supports encryption when the same key is being used for both directions. This is
+ * because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps).
+ */
+ const CIPHER_RC4 = 5;
+ /**
+ * Blowfish
+ *
+ * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and
+ * uses it (see cipher.c)
+ */
+ const CIPHER_BLOWFISH = 6;
+ /**#@-*/
+
+ /**#@+
+ * Authentication Methods
+ *
+ * @see \phpseclib\Net\SSH1::getSupportedAuthentications()
+ * @access public
+ */
+ /**
+ * .rhosts or /etc/hosts.equiv
+ */
+ const AUTH_RHOSTS = 1;
+ /**
+ * pure RSA authentication
+ */
+ const AUTH_RSA = 2;
+ /**
+ * password authentication
+ *
+ * This is the only method that is supported by this library.
+ */
+ const AUTH_PASSWORD = 3;
+ /**
+ * .rhosts with RSA host authentication
+ */
+ const AUTH_RHOSTS_RSA = 4;
+ /**#@-*/
+
+ /**#@+
+ * Terminal Modes
+ *
+ * @link http://3sp.com/content/developer/maverick-net/docs/Maverick.SSH.PseudoTerminalModesMembers.html
+ * @access private
+ */
+ const TTY_OP_END = 0;
+ /**#@-*/
+
+ /**
+ * The Response Type
+ *
+ * @see \phpseclib\Net\SSH1::_get_binary_packet()
+ * @access private
+ */
+ const RESPONSE_TYPE = 1;
+
+ /**
+ * The Response Data
+ *
+ * @see \phpseclib\Net\SSH1::_get_binary_packet()
+ * @access private
+ */
+ const RESPONSE_DATA = 2;
+
+ /**#@+
+ * Execution Bitmap Masks
+ *
+ * @see \phpseclib\Net\SSH1::bitmap
+ * @access private
+ */
+ const MASK_CONSTRUCTOR = 0x00000001;
+ const MASK_CONNECTED = 0x00000002;
+ const MASK_LOGIN = 0x00000004;
+ const MASK_SHELL = 0x00000008;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Net\SSH1::getLog()
+ */
+ /**
+ * Returns the message numbers
+ */
+ const LOG_SIMPLE = 1;
+ /**
+ * Returns the message content
+ */
+ const LOG_COMPLEX = 2;
+ /**
+ * Outputs the content real-time
+ */
+ const LOG_REALTIME = 3;
+ /**
+ * Dumps the content real-time to a file
+ */
+ const LOG_REALTIME_FILE = 4;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Net\SSH1::read()
+ */
+ /**
+ * Returns when a string matching $expect exactly is found
+ */
+ const READ_SIMPLE = 1;
+ /**
+ * Returns when a string matching the regular expression $expect is found
+ */
+ const READ_REGEX = 2;
+ /**#@-*/
+
+ /**
+ * The SSH identifier
+ *
+ * @var string
+ * @access private
+ */
+ var $identifier = 'SSH-1.5-phpseclib';
+
+ /**
+ * The Socket Object
+ *
+ * @var object
+ * @access private
+ */
+ var $fsock;
+
+ /**
+ * The cryptography object
+ *
+ * @var object
+ * @access private
+ */
+ var $crypto = false;
+
+ /**
+ * Execution Bitmap
+ *
+ * The bits that are set represent functions that have been called already. This is used to determine
+ * if a requisite function has been successfully executed. If not, an error should be thrown.
+ *
+ * @var int
+ * @access private
+ */
+ var $bitmap = 0;
+
+ /**
+ * The Server Key Public Exponent
+ *
+ * Logged for debug purposes
+ *
+ * @see self::getServerKeyPublicExponent()
+ * @var string
+ * @access private
+ */
+ var $server_key_public_exponent;
+
+ /**
+ * The Server Key Public Modulus
+ *
+ * Logged for debug purposes
+ *
+ * @see self::getServerKeyPublicModulus()
+ * @var string
+ * @access private
+ */
+ var $server_key_public_modulus;
+
+ /**
+ * The Host Key Public Exponent
+ *
+ * Logged for debug purposes
+ *
+ * @see self::getHostKeyPublicExponent()
+ * @var string
+ * @access private
+ */
+ var $host_key_public_exponent;
+
+ /**
+ * The Host Key Public Modulus
+ *
+ * Logged for debug purposes
+ *
+ * @see self::getHostKeyPublicModulus()
+ * @var string
+ * @access private
+ */
+ var $host_key_public_modulus;
+
+ /**
+ * Supported Ciphers
+ *
+ * Logged for debug purposes
+ *
+ * @see self::getSupportedCiphers()
+ * @var array
+ * @access private
+ */
+ var $supported_ciphers = array(
+ self::CIPHER_NONE => 'No encryption',
+ self::CIPHER_IDEA => 'IDEA in CFB mode',
+ self::CIPHER_DES => 'DES in CBC mode',
+ self::CIPHER_3DES => 'Triple-DES in CBC mode',
+ self::CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC',
+ self::CIPHER_RC4 => 'RC4',
+ self::CIPHER_BLOWFISH => 'Blowfish'
+ );
+
+ /**
+ * Supported Authentications
+ *
+ * Logged for debug purposes
+ *
+ * @see self::getSupportedAuthentications()
+ * @var array
+ * @access private
+ */
+ var $supported_authentications = array(
+ self::AUTH_RHOSTS => '.rhosts or /etc/hosts.equiv',
+ self::AUTH_RSA => 'pure RSA authentication',
+ self::AUTH_PASSWORD => 'password authentication',
+ self::AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication'
+ );
+
+ /**
+ * Server Identification
+ *
+ * @see self::getServerIdentification()
+ * @var string
+ * @access private
+ */
+ var $server_identification = '';
+
+ /**
+ * Protocol Flags
+ *
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $protocol_flags = array();
+
+ /**
+ * Protocol Flag Log
+ *
+ * @see self::getLog()
+ * @var array
+ * @access private
+ */
+ var $protocol_flag_log = array();
+
+ /**
+ * Message Log
+ *
+ * @see self::getLog()
+ * @var array
+ * @access private
+ */
+ var $message_log = array();
+
+ /**
+ * Real-time log file pointer
+ *
+ * @see self::_append_log()
+ * @var resource
+ * @access private
+ */
+ var $realtime_log_file;
+
+ /**
+ * Real-time log file size
+ *
+ * @see self::_append_log()
+ * @var int
+ * @access private
+ */
+ var $realtime_log_size;
+
+ /**
+ * Real-time log file wrap boolean
+ *
+ * @see self::_append_log()
+ * @var bool
+ * @access private
+ */
+ var $realtime_log_wrap;
+
+ /**
+ * Interactive Buffer
+ *
+ * @see self::read()
+ * @var array
+ * @access private
+ */
+ var $interactiveBuffer = '';
+
+ /**
+ * Timeout
+ *
+ * @see self::setTimeout()
+ * @access private
+ */
+ var $timeout;
+
+ /**
+ * Current Timeout
+ *
+ * @see self::_get_channel_packet()
+ * @access private
+ */
+ var $curTimeout;
+
+ /**
+ * Log Boundary
+ *
+ * @see self::_format_log()
+ * @access private
+ */
+ var $log_boundary = ':';
+
+ /**
+ * Log Long Width
+ *
+ * @see self::_format_log()
+ * @access private
+ */
+ var $log_long_width = 65;
+
+ /**
+ * Log Short Width
+ *
+ * @see self::_format_log()
+ * @access private
+ */
+ var $log_short_width = 16;
+
+ /**
+ * Hostname
+ *
+ * @see self::__construct()
+ * @see self::_connect()
+ * @var string
+ * @access private
+ */
+ var $host;
+
+ /**
+ * Port Number
+ *
+ * @see self::__construct()
+ * @see self::_connect()
+ * @var int
+ * @access private
+ */
+ var $port;
+
+ /**
+ * Timeout for initial connection
+ *
+ * Set by the constructor call. Calling setTimeout() is optional. If it's not called functions like
+ * exec() won't timeout unless some PHP setting forces it too. The timeout specified in the constructor,
+ * however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
+ * 10 seconds. It is used by fsockopen() in that function.
+ *
+ * @see self::__construct()
+ * @see self::_connect()
+ * @var int
+ * @access private
+ */
+ var $connectionTimeout;
+
+ /**
+ * Default cipher
+ *
+ * @see self::__construct()
+ * @see self::_connect()
+ * @var int
+ * @access private
+ */
+ var $cipher;
+
+ /**
+ * Default Constructor.
+ *
+ * Connects to an SSHv1 server
+ *
+ * @param string $host
+ * @param int $port
+ * @param int $timeout
+ * @param int $cipher
+ * @return \phpseclib\Net\SSH1
+ * @access public
+ */
+ function __construct($host, $port = 22, $timeout = 10, $cipher = self::CIPHER_3DES)
+ {
+ $this->protocol_flags = array(
+ 1 => 'NET_SSH1_MSG_DISCONNECT',
+ 2 => 'NET_SSH1_SMSG_PUBLIC_KEY',
+ 3 => 'NET_SSH1_CMSG_SESSION_KEY',
+ 4 => 'NET_SSH1_CMSG_USER',
+ 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD',
+ 10 => 'NET_SSH1_CMSG_REQUEST_PTY',
+ 12 => 'NET_SSH1_CMSG_EXEC_SHELL',
+ 13 => 'NET_SSH1_CMSG_EXEC_CMD',
+ 14 => 'NET_SSH1_SMSG_SUCCESS',
+ 15 => 'NET_SSH1_SMSG_FAILURE',
+ 16 => 'NET_SSH1_CMSG_STDIN_DATA',
+ 17 => 'NET_SSH1_SMSG_STDOUT_DATA',
+ 18 => 'NET_SSH1_SMSG_STDERR_DATA',
+ 19 => 'NET_SSH1_CMSG_EOF',
+ 20 => 'NET_SSH1_SMSG_EXITSTATUS',
+ 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION'
+ );
+
+ $this->_define_array($this->protocol_flags);
+
+ $this->host = $host;
+ $this->port = $port;
+ $this->connectionTimeout = $timeout;
+ $this->cipher = $cipher;
+ }
+
+ /**
+ * Connect to an SSHv1 server
+ *
+ * @return bool
+ * @access private
+ */
+ function _connect()
+ {
+ $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
+ if (!$this->fsock) {
+ user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
+ return false;
+ }
+
+ $this->server_identification = $init_line = fgets($this->fsock, 255);
+
+ if (defined('NET_SSH1_LOGGING')) {
+ $this->_append_log('<-', $this->server_identification);
+ $this->_append_log('->', $this->identifier . "\r\n");
+ }
+
+ if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
+ user_error('Can only connect to SSH servers');
+ return false;
+ }
+ if ($parts[1][0] != 1) {
+ user_error("Cannot connect to SSH $parts[1] servers");
+ return false;
+ }
+
+ fputs($this->fsock, $this->identifier."\r\n");
+
+ $response = $this->_get_binary_packet();
+ if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
+ user_error('Expected SSH_SMSG_PUBLIC_KEY');
+ return false;
+ }
+
+ $anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
+
+ $this->_string_shift($response[self::RESPONSE_DATA], 4);
+
+ if (strlen($response[self::RESPONSE_DATA]) < 2) {
+ return false;
+ }
+ $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
+ $server_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
+ $this->server_key_public_exponent = $server_key_public_exponent;
+
+ if (strlen($response[self::RESPONSE_DATA]) < 2) {
+ return false;
+ }
+ $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
+ $server_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
+
+ $this->server_key_public_modulus = $server_key_public_modulus;
+
+ $this->_string_shift($response[self::RESPONSE_DATA], 4);
+
+ if (strlen($response[self::RESPONSE_DATA]) < 2) {
+ return false;
+ }
+ $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
+ $host_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
+ $this->host_key_public_exponent = $host_key_public_exponent;
+
+ if (strlen($response[self::RESPONSE_DATA]) < 2) {
+ return false;
+ }
+ $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
+ $host_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
+
+ $this->host_key_public_modulus = $host_key_public_modulus;
+
+ $this->_string_shift($response[self::RESPONSE_DATA], 4);
+
+ // get a list of the supported ciphers
+ if (strlen($response[self::RESPONSE_DATA]) < 4) {
+ return false;
+ }
+ extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4)));
+
+ foreach ($this->supported_ciphers as $mask => $name) {
+ if (($supported_ciphers_mask & (1 << $mask)) == 0) {
+ unset($this->supported_ciphers[$mask]);
+ }
+ }
+
+ // get a list of the supported authentications
+ if (strlen($response[self::RESPONSE_DATA]) < 4) {
+ return false;
+ }
+ extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4)));
+ foreach ($this->supported_authentications as $mask => $name) {
+ if (($supported_authentications_mask & (1 << $mask)) == 0) {
+ unset($this->supported_authentications[$mask]);
+ }
+ }
+
+ $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
+
+ $session_key = Random::string(32);
+ $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
+
+ if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
+ $double_encrypted_session_key = $this->_rsa_crypt(
+ $double_encrypted_session_key,
+ array(
+ $server_key_public_exponent,
+ $server_key_public_modulus
+ )
+ );
+ $double_encrypted_session_key = $this->_rsa_crypt(
+ $double_encrypted_session_key,
+ array(
+ $host_key_public_exponent,
+ $host_key_public_modulus
+ )
+ );
+ } else {
+ $double_encrypted_session_key = $this->_rsa_crypt(
+ $double_encrypted_session_key,
+ array(
+ $host_key_public_exponent,
+ $host_key_public_modulus
+ )
+ );
+ $double_encrypted_session_key = $this->_rsa_crypt(
+ $double_encrypted_session_key,
+ array(
+ $server_key_public_exponent,
+ $server_key_public_modulus
+ )
+ );
+ }
+
+ $cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : self::CIPHER_3DES;
+ $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_SESSION_KEY');
+ return false;
+ }
+
+ switch ($cipher) {
+ //case self::CIPHER_NONE:
+ // $this->crypto = new \phpseclib\Crypt\Null();
+ // break;
+ case self::CIPHER_DES:
+ $this->crypto = new DES();
+ $this->crypto->disablePadding();
+ $this->crypto->enableContinuousBuffer();
+ $this->crypto->setKey(substr($session_key, 0, 8));
+ break;
+ case self::CIPHER_3DES:
+ $this->crypto = new TripleDES(TripleDES::MODE_3CBC);
+ $this->crypto->disablePadding();
+ $this->crypto->enableContinuousBuffer();
+ $this->crypto->setKey(substr($session_key, 0, 24));
+ break;
+ //case self::CIPHER_RC4:
+ // $this->crypto = new RC4();
+ // $this->crypto->enableContinuousBuffer();
+ // $this->crypto->setKey(substr($session_key, 0, 16));
+ // break;
+ }
+
+ $response = $this->_get_binary_packet();
+
+ if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
+ user_error('Expected SSH_SMSG_SUCCESS');
+ return false;
+ }
+
+ $this->bitmap = self::MASK_CONNECTED;
+
+ return true;
+ }
+
+ /**
+ * Login
+ *
+ * @param string $username
+ * @param string $password
+ * @return bool
+ * @access public
+ */
+ function login($username, $password = '')
+ {
+ if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
+ $this->bitmap |= self::MASK_CONSTRUCTOR;
+ if (!$this->_connect()) {
+ return false;
+ }
+ }
+
+ if (!($this->bitmap & self::MASK_CONNECTED)) {
+ return false;
+ }
+
+ $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_USER');
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+
+ if ($response === true) {
+ return false;
+ }
+ if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ } elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
+ user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
+ return false;
+ }
+
+ $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
+ return false;
+ }
+
+ // remove the username and password from the last logged packet
+ if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == self::LOG_COMPLEX) {
+ $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password');
+ $this->message_log[count($this->message_log) - 1] = $data;
+ }
+
+ $response = $this->_get_binary_packet();
+
+ if ($response === true) {
+ return false;
+ }
+ if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ } elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
+ return false;
+ } else {
+ user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
+ return false;
+ }
+ }
+
+ /**
+ * Set Timeout
+ *
+ * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
+ * Setting $timeout to false or 0 will mean there is no timeout.
+ *
+ * @param mixed $timeout
+ */
+ function setTimeout($timeout)
+ {
+ $this->timeout = $this->curTimeout = $timeout;
+ }
+
+ /**
+ * Executes a command on a non-interactive shell, returns the output, and quits.
+ *
+ * An SSH1 server will close the connection after a command has been executed on a non-interactive shell. SSH2
+ * servers don't, however, this isn't an SSH2 client. The way this works, on the server, is by initiating a
+ * shell with the -s option, as discussed in the following links:
+ *
+ * {@link http://www.faqs.org/docs/bashman/bashref_65.html http://www.faqs.org/docs/bashman/bashref_65.html}
+ * {@link http://www.faqs.org/docs/bashman/bashref_62.html http://www.faqs.org/docs/bashman/bashref_62.html}
+ *
+ * To execute further commands, a new \phpseclib\Net\SSH1 object will need to be created.
+ *
+ * Returns false on failure and the output, otherwise.
+ *
+ * @see self::interactiveRead()
+ * @see self::interactiveWrite()
+ * @param string $cmd
+ * @return mixed
+ * @access public
+ */
+ function exec($cmd, $block = true)
+ {
+ if (!($this->bitmap & self::MASK_LOGIN)) {
+ user_error('Operation disallowed prior to login()');
+ return false;
+ }
+
+ $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_EXEC_CMD');
+ return false;
+ }
+
+ if (!$block) {
+ return true;
+ }
+
+ $output = '';
+ $response = $this->_get_binary_packet();
+
+ if ($response !== false) {
+ do {
+ $output.= substr($response[self::RESPONSE_DATA], 4);
+ $response = $this->_get_binary_packet();
+ } while (is_array($response) && $response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);
+ }
+
+ $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
+
+ // i don't think it's really all that important if this packet gets sent or not.
+ $this->_send_binary_packet($data);
+
+ fclose($this->fsock);
+
+ // reset the execution bitmap - a new \phpseclib\Net\SSH1 object needs to be created.
+ $this->bitmap = 0;
+
+ return $output;
+ }
+
+ /**
+ * Creates an interactive shell
+ *
+ * @see self::interactiveRead()
+ * @see self::interactiveWrite()
+ * @return bool
+ * @access private
+ */
+ function _initShell()
+ {
+ // connect using the sample parameters in protocol-1.5.txt.
+ // according to wikipedia.org's entry on text terminals, "the fundamental type of application running on a text
+ // terminal is a command line interpreter or shell". thus, opening a terminal session to run the shell.
+ $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_REQUEST_PTY');
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+
+ if ($response === true) {
+ return false;
+ }
+ if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
+ user_error('Expected SSH_SMSG_SUCCESS');
+ return false;
+ }
+
+ $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_EXEC_SHELL');
+ return false;
+ }
+
+ $this->bitmap |= self::MASK_SHELL;
+
+ //stream_set_blocking($this->fsock, 0);
+
+ return true;
+ }
+
+ /**
+ * Inputs a command into an interactive shell.
+ *
+ * @see self::interactiveWrite()
+ * @param string $cmd
+ * @return bool
+ * @access public
+ */
+ function write($cmd)
+ {
+ return $this->interactiveWrite($cmd);
+ }
+
+ /**
+ * Returns the output of an interactive shell when there's a match for $expect
+ *
+ * $expect can take the form of a string literal or, if $mode == self::READ_REGEX,
+ * a regular expression.
+ *
+ * @see self::write()
+ * @param string $expect
+ * @param int $mode
+ * @return bool
+ * @access public
+ */
+ function read($expect, $mode = self::READ_SIMPLE)
+ {
+ if (!($this->bitmap & self::MASK_LOGIN)) {
+ user_error('Operation disallowed prior to login()');
+ return false;
+ }
+
+ if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
+ user_error('Unable to initiate an interactive shell session');
+ return false;
+ }
+
+ $match = $expect;
+ while (true) {
+ if ($mode == self::READ_REGEX) {
+ preg_match($expect, $this->interactiveBuffer, $matches);
+ $match = isset($matches[0]) ? $matches[0] : '';
+ }
+ $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
+ if ($pos !== false) {
+ return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
+ }
+ $response = $this->_get_binary_packet();
+
+ if ($response === true) {
+ return $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
+ }
+ $this->interactiveBuffer.= substr($response[self::RESPONSE_DATA], 4);
+ }
+ }
+
+ /**
+ * Inputs a command into an interactive shell.
+ *
+ * @see self::interactiveRead()
+ * @param string $cmd
+ * @return bool
+ * @access public
+ */
+ function interactiveWrite($cmd)
+ {
+ if (!($this->bitmap & self::MASK_LOGIN)) {
+ user_error('Operation disallowed prior to login()');
+ return false;
+ }
+
+ if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
+ user_error('Unable to initiate an interactive shell session');
+ return false;
+ }
+
+ $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
+
+ if (!$this->_send_binary_packet($data)) {
+ user_error('Error sending SSH_CMSG_STDIN');
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the output of an interactive shell when no more output is available.
+ *
+ * Requires PHP 4.3.0 or later due to the use of the stream_select() function. If you see stuff like
+ * "^[[00m", you're seeing ANSI escape codes. According to
+ * {@link http://support.microsoft.com/kb/101875 How to Enable ANSI.SYS in a Command Window}, "Windows NT
+ * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user,
+ * there's not going to be much recourse.
+ *
+ * @see self::interactiveRead()
+ * @return string
+ * @access public
+ */
+ function interactiveRead()
+ {
+ if (!($this->bitmap & self::MASK_LOGIN)) {
+ user_error('Operation disallowed prior to login()');
+ return false;
+ }
+
+ if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
+ user_error('Unable to initiate an interactive shell session');
+ return false;
+ }
+
+ $read = array($this->fsock);
+ $write = $except = null;
+ if (stream_select($read, $write, $except, 0)) {
+ $response = $this->_get_binary_packet();
+ return substr($response[self::RESPONSE_DATA], 4);
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Disconnect
+ *
+ * @access public
+ */
+ function disconnect()
+ {
+ $this->_disconnect();
+ }
+
+ /**
+ * Destructor.
+ *
+ * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
+ * disconnect().
+ *
+ * @access public
+ */
+ function __destruct()
+ {
+ $this->_disconnect();
+ }
+
+ /**
+ * Disconnect
+ *
+ * @param string $msg
+ * @access private
+ */
+ function _disconnect($msg = 'Client Quit')
+ {
+ if ($this->bitmap) {
+ $data = pack('C', NET_SSH1_CMSG_EOF);
+ $this->_send_binary_packet($data);
+ /*
+ $response = $this->_get_binary_packet();
+ if ($response === true) {
+ $response = array(self::RESPONSE_TYPE => -1);
+ }
+ switch ($response[self::RESPONSE_TYPE]) {
+ case NET_SSH1_SMSG_EXITSTATUS:
+ $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
+ break;
+ default:
+ $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
+ }
+ */
+ $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
+
+ $this->_send_binary_packet($data);
+ fclose($this->fsock);
+ $this->bitmap = 0;
+ }
+ }
+
+ /**
+ * Gets Binary Packets
+ *
+ * See 'The Binary Packet Protocol' of protocol-1.5.txt for more info.
+ *
+ * Also, this function could be improved upon by adding detection for the following exploit:
+ * http://www.securiteam.com/securitynews/5LP042K3FY.html
+ *
+ * @see self::_send_binary_packet()
+ * @return array
+ * @access private
+ */
+ function _get_binary_packet()
+ {
+ if (feof($this->fsock)) {
+ //user_error('connection closed prematurely');
+ return false;
+ }
+
+ if ($this->curTimeout) {
+ $read = array($this->fsock);
+ $write = $except = null;
+
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
+ $sec = floor($this->curTimeout);
+ $usec = 1000000 * ($this->curTimeout - $sec);
+ // on windows this returns a "Warning: Invalid CRT parameters detected" error
+ if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
+ //$this->_disconnect('Timeout');
+ return true;
+ }
+ $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
+ $this->curTimeout-= $elapsed;
+ }
+
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
+ $data = fread($this->fsock, 4);
+ if (strlen($data) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $data);
+
+ $padding_length = 8 - ($temp['length'] & 7);
+ $length = $temp['length'] + $padding_length;
+ $raw = '';
+
+ while ($length > 0) {
+ $temp = fread($this->fsock, $length);
+ $raw.= $temp;
+ $length-= strlen($temp);
+ }
+ $stop = strtok(microtime(), ' ') + strtok('');
+
+ if (strlen($raw) && $this->crypto !== false) {
+ $raw = $this->crypto->decrypt($raw);
+ }
+
+ $padding = substr($raw, 0, $padding_length);
+ $type = $raw[$padding_length];
+ $data = substr($raw, $padding_length + 1, -4);
+
+ if (strlen($raw) < 4) {
+ return false;
+ }
+ $temp = unpack('Ncrc', substr($raw, -4));
+
+ //if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) {
+ // user_error('Bad CRC in packet from server');
+ // return false;
+ //}
+
+ $type = ord($type);
+
+ if (defined('NET_SSH1_LOGGING')) {
+ $temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN';
+ $temp = '<- ' . $temp .
+ ' (' . round($stop - $start, 4) . 's)';
+ $this->_append_log($temp, $data);
+ }
+
+ return array(
+ self::RESPONSE_TYPE => $type,
+ self::RESPONSE_DATA => $data
+ );
+ }
+
+ /**
+ * Sends Binary Packets
+ *
+ * Returns true on success, false on failure.
+ *
+ * @see self::_get_binary_packet()
+ * @param string $data
+ * @return bool
+ * @access private
+ */
+ function _send_binary_packet($data)
+ {
+ if (feof($this->fsock)) {
+ //user_error('connection closed prematurely');
+ return false;
+ }
+
+ $length = strlen($data) + 4;
+
+ $padding = Random::string(8 - ($length & 7));
+
+ $orig = $data;
+ $data = $padding . $data;
+ $data.= pack('N', $this->_crc($data));
+
+ if ($this->crypto !== false) {
+ $data = $this->crypto->encrypt($data);
+ }
+
+ $packet = pack('Na*', $length, $data);
+
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
+ $result = strlen($packet) == fputs($this->fsock, $packet);
+ $stop = strtok(microtime(), ' ') + strtok('');
+
+ if (defined('NET_SSH1_LOGGING')) {
+ $temp = isset($this->protocol_flags[ord($orig[0])]) ? $this->protocol_flags[ord($orig[0])] : 'UNKNOWN';
+ $temp = '-> ' . $temp .
+ ' (' . round($stop - $start, 4) . 's)';
+ $this->_append_log($temp, $orig);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Cyclic Redundancy Check (CRC)
+ *
+ * PHP's crc32 function is implemented slightly differently than the one that SSH v1 uses, so
+ * we've reimplemented it. A more detailed discussion of the differences can be found after
+ * $crc_lookup_table's initialization.
+ *
+ * @see self::_get_binary_packet()
+ * @see self::_send_binary_packet()
+ * @param string $data
+ * @return int
+ * @access private
+ */
+ function _crc($data)
+ {
+ static $crc_lookup_table = array(
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+ );
+
+ // For this function to yield the same output as PHP's crc32 function, $crc would have to be
+ // set to 0xFFFFFFFF, initially - not 0x00000000 as it currently is.
+ $crc = 0x00000000;
+ $length = strlen($data);
+
+ for ($i=0; $i<$length; $i++) {
+ // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all
+ // be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example,
+ // yields 0xFF800000 - not 0x00800000. The following link elaborates:
+ // http://www.php.net/manual/en/language.operators.bitwise.php#57281
+ $crc = (($crc >> 8) & 0x00FFFFFF) ^ $crc_lookup_table[($crc & 0xFF) ^ ord($data[$i])];
+ }
+
+ // In addition to having to set $crc to 0xFFFFFFFF, initially, the return value must be XOR'd with
+ // 0xFFFFFFFF for this function to return the same thing that PHP's crc32 function would.
+ return $crc;
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @return string
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+
+ /**
+ * RSA Encrypt
+ *
+ * Returns mod(pow($m, $e), $n), where $n should be the product of two (large) primes $p and $q and where $e
+ * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that
+ * calls this call modexp, instead, but I think this makes things clearer, maybe...
+ *
+ * @see self::__construct()
+ * @param BigInteger $m
+ * @param array $key
+ * @return BigInteger
+ * @access private
+ */
+ function _rsa_crypt($m, $key)
+ {
+ /*
+ $rsa = new RSA();
+ $rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW);
+ $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
+ return $rsa->encrypt($m);
+ */
+
+ // To quote from protocol-1.5.txt:
+ // The most significant byte (which is only partial as the value must be
+ // less than the public modulus, which is never a power of two) is zero.
+ //
+ // The next byte contains the value 2 (which stands for public-key
+ // encrypted data in the PKCS standard [PKCS#1]). Then, there are non-
+ // zero random bytes to fill any unused space, a zero byte, and the data
+ // to be encrypted in the least significant bytes, the last byte of the
+ // data in the least significant byte.
+
+ // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation",
+ // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL:
+ // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
+ $modulus = $key[1]->toBytes();
+ $length = strlen($modulus) - strlen($m) - 3;
+ $random = '';
+ while (strlen($random) != $length) {
+ $block = Random::string($length - strlen($random));
+ $block = str_replace("\x00", '', $block);
+ $random.= $block;
+ }
+ $temp = chr(0) . chr(2) . $random . chr(0) . $m;
+
+ $m = new BigInteger($temp, 256);
+ $m = $m->modPow($key[0], $key[1]);
+
+ return $m->toBytes();
+ }
+
+ /**
+ * Define Array
+ *
+ * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
+ * named constants from it, using the value as the name of the constant and the index as the value of the constant.
+ * If any of the constants that would be defined already exists, none of the constants will be defined.
+ *
+ * @param array $array
+ * @access private
+ */
+ function _define_array()
+ {
+ $args = func_get_args();
+ foreach ($args as $arg) {
+ foreach ($arg as $key => $value) {
+ if (!defined($value)) {
+ define($value, $key);
+ } else {
+ break 2;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a log of the packets that have been sent and received.
+ *
+ * Returns a string if NET_SSH1_LOGGING == self::LOG_COMPLEX, an array if NET_SSH1_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING')
+ *
+ * @access public
+ * @return array|false|string
+ */
+ function getLog()
+ {
+ if (!defined('NET_SSH1_LOGGING')) {
+ return false;
+ }
+
+ switch (NET_SSH1_LOGGING) {
+ case self::LOG_SIMPLE:
+ return $this->message_number_log;
+ break;
+ case self::LOG_COMPLEX:
+ return $this->_format_log($this->message_log, $this->protocol_flags_log);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Formats a log for printing
+ *
+ * @param array $message_log
+ * @param array $message_number_log
+ * @access private
+ * @return string
+ */
+ function _format_log($message_log, $message_number_log)
+ {
+ $output = '';
+ for ($i = 0; $i < count($message_log); $i++) {
+ $output.= $message_number_log[$i] . "\r\n";
+ $current_log = $message_log[$i];
+ $j = 0;
+ do {
+ if (strlen($current_log)) {
+ $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
+ }
+ $fragment = $this->_string_shift($current_log, $this->log_short_width);
+ $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary));
+ // replace non ASCII printable characters with dots
+ // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
+ // also replace < with a . since < messes up the output on web browsers
+ $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
+ $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n";
+ $j++;
+ } while (strlen($current_log));
+ $output.= "\r\n";
+ }
+
+ return $output;
+ }
+
+ /**
+ * Helper function for _format_log
+ *
+ * For use with preg_replace_callback()
+ *
+ * @param array $matches
+ * @access private
+ * @return string
+ */
+ function _format_log_helper($matches)
+ {
+ return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
+ }
+
+ /**
+ * Return the server key public exponent
+ *
+ * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
+ * the raw bytes. This behavior is similar to PHP's md5() function.
+ *
+ * @param bool $raw_output
+ * @return string
+ * @access public
+ */
+ function getServerKeyPublicExponent($raw_output = false)
+ {
+ return $raw_output ? $this->server_key_public_exponent->toBytes() : $this->server_key_public_exponent->toString();
+ }
+
+ /**
+ * Return the server key public modulus
+ *
+ * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
+ * the raw bytes. This behavior is similar to PHP's md5() function.
+ *
+ * @param bool $raw_output
+ * @return string
+ * @access public
+ */
+ function getServerKeyPublicModulus($raw_output = false)
+ {
+ return $raw_output ? $this->server_key_public_modulus->toBytes() : $this->server_key_public_modulus->toString();
+ }
+
+ /**
+ * Return the host key public exponent
+ *
+ * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
+ * the raw bytes. This behavior is similar to PHP's md5() function.
+ *
+ * @param bool $raw_output
+ * @return string
+ * @access public
+ */
+ function getHostKeyPublicExponent($raw_output = false)
+ {
+ return $raw_output ? $this->host_key_public_exponent->toBytes() : $this->host_key_public_exponent->toString();
+ }
+
+ /**
+ * Return the host key public modulus
+ *
+ * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
+ * the raw bytes. This behavior is similar to PHP's md5() function.
+ *
+ * @param bool $raw_output
+ * @return string
+ * @access public
+ */
+ function getHostKeyPublicModulus($raw_output = false)
+ {
+ return $raw_output ? $this->host_key_public_modulus->toBytes() : $this->host_key_public_modulus->toString();
+ }
+
+ /**
+ * Return a list of ciphers supported by SSH1 server.
+ *
+ * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output
+ * is set to true, returns, instead, an array of constants. ie. instead of array('Triple-DES in CBC mode'), you'll
+ * get array(self::CIPHER_3DES).
+ *
+ * @param bool $raw_output
+ * @return array
+ * @access public
+ */
+ function getSupportedCiphers($raw_output = false)
+ {
+ return $raw_output ? array_keys($this->supported_ciphers) : array_values($this->supported_ciphers);
+ }
+
+ /**
+ * Return a list of authentications supported by SSH1 server.
+ *
+ * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output
+ * is set to true, returns, instead, an array of constants. ie. instead of array('password authentication'), you'll
+ * get array(self::AUTH_PASSWORD).
+ *
+ * @param bool $raw_output
+ * @return array
+ * @access public
+ */
+ function getSupportedAuthentications($raw_output = false)
+ {
+ return $raw_output ? array_keys($this->supported_authentications) : array_values($this->supported_authentications);
+ }
+
+ /**
+ * Return the server identification.
+ *
+ * @return string
+ * @access public
+ */
+ function getServerIdentification()
+ {
+ return rtrim($this->server_identification);
+ }
+
+ /**
+ * Logs data packets
+ *
+ * Makes sure that only the last 1MB worth of packets will be logged
+ *
+ * @param string $data
+ * @access private
+ */
+ function _append_log($protocol_flags, $message)
+ {
+ switch (NET_SSH1_LOGGING) {
+ // useful for benchmarks
+ case self::LOG_SIMPLE:
+ $this->protocol_flags_log[] = $protocol_flags;
+ break;
+ // the most useful log for SSH1
+ case self::LOG_COMPLEX:
+ $this->protocol_flags_log[] = $protocol_flags;
+ $this->_string_shift($message);
+ $this->log_size+= strlen($message);
+ $this->message_log[] = $message;
+ while ($this->log_size > self::LOG_MAX_SIZE) {
+ $this->log_size-= strlen(array_shift($this->message_log));
+ array_shift($this->protocol_flags_log);
+ }
+ break;
+ // dump the output out realtime; packets may be interspersed with non packets,
+ // passwords won't be filtered out and select other packets may not be correctly
+ // identified
+ case self::LOG_REALTIME:
+ echo "<pre>\r\n" . $this->_format_log(array($message), array($protocol_flags)) . "\r\n</pre>\r\n";
+ @flush();
+ @ob_flush();
+ break;
+ // basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE
+ // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
+ // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
+ // at the beginning of the file
+ case self::LOG_REALTIME_FILE:
+ if (!isset($this->realtime_log_file)) {
+ // PHP doesn't seem to like using constants in fopen()
+ $filename = self::LOG_REALTIME_FILE;
+ $fp = fopen($filename, 'w');
+ $this->realtime_log_file = $fp;
+ }
+ if (!is_resource($this->realtime_log_file)) {
+ break;
+ }
+ $entry = $this->_format_log(array($message), array($protocol_flags));
+ if ($this->realtime_log_wrap) {
+ $temp = "<<< START >>>\r\n";
+ $entry.= $temp;
+ fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
+ }
+ $this->realtime_log_size+= strlen($entry);
+ if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
+ fseek($this->realtime_log_file, 0);
+ $this->realtime_log_size = strlen($entry);
+ $this->realtime_log_wrap = true;
+ }
+ fputs($this->realtime_log_file, $entry);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP implementation of SSHv2.
+ *
+ * PHP version 5
+ *
+ * Here are some examples of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
+ * if (!$ssh->login('username', 'password')) {
+ * exit('Login Failed');
+ * }
+ *
+ * echo $ssh->exec('pwd');
+ * echo $ssh->exec('ls -la');
+ * ?>
+ * </code>
+ *
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $key = new \phpseclib\Crypt\RSA();
+ * //$key->setPassword('whatever');
+ * $key->loadKey(file_get_contents('privatekey'));
+ *
+ * $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
+ * if (!$ssh->login('username', $key)) {
+ * exit('Login Failed');
+ * }
+ *
+ * echo $ssh->read('username@username:~$');
+ * $ssh->write("ls -la\n");
+ * echo $ssh->read('username@username:~$');
+ * ?>
+ * </code>
+ *
+ * @category Net
+ * @package SSH2
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Net;
+
+use phpseclib\Crypt\Base;
+use phpseclib\Crypt\Blowfish;
+use phpseclib\Crypt\Hash;
+use phpseclib\Crypt\Random;
+use phpseclib\Crypt\RC4;
+use phpseclib\Crypt\Rijndael;
+use phpseclib\Crypt\RSA;
+use phpseclib\Crypt\TripleDES;
+use phpseclib\Crypt\Twofish;
+use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
+use phpseclib\System\SSH\Agent;
+
+/**
+ * Pure-PHP implementation of SSHv2.
+ *
+ * @package SSH2
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class SSH2
+{
+ /**#@+
+ * Execution Bitmap Masks
+ *
+ * @see \phpseclib\Net\SSH2::bitmap
+ * @access private
+ */
+ const MASK_CONSTRUCTOR = 0x00000001;
+ const MASK_CONNECTED = 0x00000002;
+ const MASK_LOGIN_REQ = 0x00000004;
+ const MASK_LOGIN = 0x00000008;
+ const MASK_SHELL = 0x00000010;
+ const MASK_WINDOW_ADJUST = 0x00000020;
+ /**#@-*/
+
+ /**#@+
+ * Channel constants
+ *
+ * RFC4254 refers not to client and server channels but rather to sender and recipient channels. we don't refer
+ * to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with
+ * a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a
+ * recepient channel. at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel
+ * would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snipet:
+ * The 'recipient channel' is the channel number given in the original
+ * open request, and 'sender channel' is the channel number allocated by
+ * the other side.
+ *
+ * @see \phpseclib\Net\SSH2::_send_channel_packet()
+ * @see \phpseclib\Net\SSH2::_get_channel_packet()
+ * @access private
+ */
+ const CHANNEL_EXEC = 1; // PuTTy uses 0x100
+ const CHANNEL_SHELL = 2;
+ const CHANNEL_SUBSYSTEM = 3;
+ const CHANNEL_AGENT_FORWARD = 4;
+ const CHANNEL_KEEP_ALIVE = 5;
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Net\SSH2::getLog()
+ */
+ /**
+ * Returns the message numbers
+ */
+ const LOG_SIMPLE = 1;
+ /**
+ * Returns the message content
+ */
+ const LOG_COMPLEX = 2;
+ /**
+ * Outputs the content real-time
+ */
+ const LOG_REALTIME = 3;
+ /**
+ * Dumps the content real-time to a file
+ */
+ const LOG_REALTIME_FILE = 4;
+ /**
+ * Make sure that the log never gets larger than this
+ */
+ const LOG_MAX_SIZE = 1048576; // 1024 * 1024
+ /**#@-*/
+
+ /**#@+
+ * @access public
+ * @see \phpseclib\Net\SSH2::read()
+ */
+ /**
+ * Returns when a string matching $expect exactly is found
+ */
+ const READ_SIMPLE = 1;
+ /**
+ * Returns when a string matching the regular expression $expect is found
+ */
+ const READ_REGEX = 2;
+ /**
+ * Returns whenever a data packet is received.
+ *
+ * Some data packets may only contain a single character so it may be necessary
+ * to call read() multiple times when using this option
+ */
+ const READ_NEXT = 3;
+ /**#@-*/
+
+ /**
+ * The SSH identifier
+ *
+ * @var string
+ * @access private
+ */
+ var $identifier;
+
+ /**
+ * The Socket Object
+ *
+ * @var object
+ * @access private
+ */
+ var $fsock;
+
+ /**
+ * Execution Bitmap
+ *
+ * The bits that are set represent functions that have been called already. This is used to determine
+ * if a requisite function has been successfully executed. If not, an error should be thrown.
+ *
+ * @var int
+ * @access private
+ */
+ var $bitmap = 0;
+
+ /**
+ * Error information
+ *
+ * @see self::getErrors()
+ * @see self::getLastError()
+ * @var string
+ * @access private
+ */
+ var $errors = array();
+
+ /**
+ * Server Identifier
+ *
+ * @see self::getServerIdentification()
+ * @var array|false
+ * @access private
+ */
+ var $server_identifier = false;
+
+ /**
+ * Key Exchange Algorithms
+ *
+ * @see self::getKexAlgorithims()
+ * @var array|false
+ * @access private
+ */
+ var $kex_algorithms = false;
+
+ /**
+ * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
+ *
+ * @see self::_key_exchange()
+ * @var int
+ * @access private
+ */
+ var $kex_dh_group_size_min = 1536;
+
+ /**
+ * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
+ *
+ * @see self::_key_exchange()
+ * @var int
+ * @access private
+ */
+ var $kex_dh_group_size_preferred = 2048;
+
+ /**
+ * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
+ *
+ * @see self::_key_exchange()
+ * @var int
+ * @access private
+ */
+ var $kex_dh_group_size_max = 4096;
+
+ /**
+ * Server Host Key Algorithms
+ *
+ * @see self::getServerHostKeyAlgorithms()
+ * @var array|false
+ * @access private
+ */
+ var $server_host_key_algorithms = false;
+
+ /**
+ * Encryption Algorithms: Client to Server
+ *
+ * @see self::getEncryptionAlgorithmsClient2Server()
+ * @var array|false
+ * @access private
+ */
+ var $encryption_algorithms_client_to_server = false;
+
+ /**
+ * Encryption Algorithms: Server to Client
+ *
+ * @see self::getEncryptionAlgorithmsServer2Client()
+ * @var array|false
+ * @access private
+ */
+ var $encryption_algorithms_server_to_client = false;
+
+ /**
+ * MAC Algorithms: Client to Server
+ *
+ * @see self::getMACAlgorithmsClient2Server()
+ * @var array|false
+ * @access private
+ */
+ var $mac_algorithms_client_to_server = false;
+
+ /**
+ * MAC Algorithms: Server to Client
+ *
+ * @see self::getMACAlgorithmsServer2Client()
+ * @var array|false
+ * @access private
+ */
+ var $mac_algorithms_server_to_client = false;
+
+ /**
+ * Compression Algorithms: Client to Server
+ *
+ * @see self::getCompressionAlgorithmsClient2Server()
+ * @var array|false
+ * @access private
+ */
+ var $compression_algorithms_client_to_server = false;
+
+ /**
+ * Compression Algorithms: Server to Client
+ *
+ * @see self::getCompressionAlgorithmsServer2Client()
+ * @var array|false
+ * @access private
+ */
+ var $compression_algorithms_server_to_client = false;
+
+ /**
+ * Languages: Server to Client
+ *
+ * @see self::getLanguagesServer2Client()
+ * @var array|false
+ * @access private
+ */
+ var $languages_server_to_client = false;
+
+ /**
+ * Languages: Client to Server
+ *
+ * @see self::getLanguagesClient2Server()
+ * @var array|false
+ * @access private
+ */
+ var $languages_client_to_server = false;
+
+ /**
+ * Block Size for Server to Client Encryption
+ *
+ * "Note that the length of the concatenation of 'packet_length',
+ * 'padding_length', 'payload', and 'random padding' MUST be a multiple
+ * of the cipher block size or 8, whichever is larger. This constraint
+ * MUST be enforced, even when using stream ciphers."
+ *
+ * -- http://tools.ietf.org/html/rfc4253#section-6
+ *
+ * @see self::__construct()
+ * @see self::_send_binary_packet()
+ * @var int
+ * @access private
+ */
+ var $encrypt_block_size = 8;
+
+ /**
+ * Block Size for Client to Server Encryption
+ *
+ * @see self::__construct()
+ * @see self::_get_binary_packet()
+ * @var int
+ * @access private
+ */
+ var $decrypt_block_size = 8;
+
+ /**
+ * Server to Client Encryption Object
+ *
+ * @see self::_get_binary_packet()
+ * @var object
+ * @access private
+ */
+ var $decrypt = false;
+
+ /**
+ * Client to Server Encryption Object
+ *
+ * @see self::_send_binary_packet()
+ * @var object
+ * @access private
+ */
+ var $encrypt = false;
+
+ /**
+ * Client to Server HMAC Object
+ *
+ * @see self::_send_binary_packet()
+ * @var object
+ * @access private
+ */
+ var $hmac_create = false;
+
+ /**
+ * Server to Client HMAC Object
+ *
+ * @see self::_get_binary_packet()
+ * @var object
+ * @access private
+ */
+ var $hmac_check = false;
+
+ /**
+ * Size of server to client HMAC
+ *
+ * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read.
+ * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
+ * append it.
+ *
+ * @see self::_get_binary_packet()
+ * @var int
+ * @access private
+ */
+ var $hmac_size = false;
+
+ /**
+ * Server Public Host Key
+ *
+ * @see self::getServerPublicHostKey()
+ * @var string
+ * @access private
+ */
+ var $server_public_host_key;
+
+ /**
+ * Session identifier
+ *
+ * "The exchange hash H from the first key exchange is additionally
+ * used as the session identifier, which is a unique identifier for
+ * this connection."
+ *
+ * -- http://tools.ietf.org/html/rfc4253#section-7.2
+ *
+ * @see self::_key_exchange()
+ * @var string
+ * @access private
+ */
+ var $session_id = false;
+
+ /**
+ * Exchange hash
+ *
+ * The current exchange hash
+ *
+ * @see self::_key_exchange()
+ * @var string
+ * @access private
+ */
+ var $exchange_hash = false;
+
+ /**
+ * Message Numbers
+ *
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $message_numbers = array();
+
+ /**
+ * Disconnection Message 'reason codes' defined in RFC4253
+ *
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $disconnect_reasons = array();
+
+ /**
+ * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
+ *
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $channel_open_failure_reasons = array();
+
+ /**
+ * Terminal Modes
+ *
+ * @link http://tools.ietf.org/html/rfc4254#section-8
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $terminal_modes = array();
+
+ /**
+ * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
+ *
+ * @link http://tools.ietf.org/html/rfc4254#section-5.2
+ * @see self::__construct()
+ * @var array
+ * @access private
+ */
+ var $channel_extended_data_type_codes = array();
+
+ /**
+ * Send Sequence Number
+ *
+ * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
+ *
+ * @see self::_send_binary_packet()
+ * @var int
+ * @access private
+ */
+ var $send_seq_no = 0;
+
+ /**
+ * Get Sequence Number
+ *
+ * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
+ *
+ * @see self::_get_binary_packet()
+ * @var int
+ * @access private
+ */
+ var $get_seq_no = 0;
+
+ /**
+ * Server Channels
+ *
+ * Maps client channels to server channels
+ *
+ * @see self::_get_channel_packet()
+ * @see self::exec()
+ * @var array
+ * @access private
+ */
+ var $server_channels = array();
+
+ /**
+ * Channel Buffers
+ *
+ * If a client requests a packet from one channel but receives two packets from another those packets should
+ * be placed in a buffer
+ *
+ * @see self::_get_channel_packet()
+ * @see self::exec()
+ * @var array
+ * @access private
+ */
+ var $channel_buffers = array();
+
+ /**
+ * Channel Status
+ *
+ * Contains the type of the last sent message
+ *
+ * @see self::_get_channel_packet()
+ * @var array
+ * @access private
+ */
+ var $channel_status = array();
+
+ /**
+ * Packet Size
+ *
+ * Maximum packet size indexed by channel
+ *
+ * @see self::_send_channel_packet()
+ * @var array
+ * @access private
+ */
+ var $packet_size_client_to_server = array();
+
+ /**
+ * Message Number Log
+ *
+ * @see self::getLog()
+ * @var array
+ * @access private
+ */
+ var $message_number_log = array();
+
+ /**
+ * Message Log
+ *
+ * @see self::getLog()
+ * @var array
+ * @access private
+ */
+ var $message_log = array();
+
+ /**
+ * The Window Size
+ *
+ * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB)
+ *
+ * @var int
+ * @see self::_send_channel_packet()
+ * @see self::exec()
+ * @access private
+ */
+ var $window_size = 0x7FFFFFFF;
+
+ /**
+ * Window size, server to client
+ *
+ * Window size indexed by channel
+ *
+ * @see self::_send_channel_packet()
+ * @var array
+ * @access private
+ */
+ var $window_size_server_to_client = array();
+
+ /**
+ * Window size, client to server
+ *
+ * Window size indexed by channel
+ *
+ * @see self::_get_channel_packet()
+ * @var array
+ * @access private
+ */
+ var $window_size_client_to_server = array();
+
+ /**
+ * Server signature
+ *
+ * Verified against $this->session_id
+ *
+ * @see self::getServerPublicHostKey()
+ * @var string
+ * @access private
+ */
+ var $signature = '';
+
+ /**
+ * Server signature format
+ *
+ * ssh-rsa or ssh-dss.
+ *
+ * @see self::getServerPublicHostKey()
+ * @var string
+ * @access private
+ */
+ var $signature_format = '';
+
+ /**
+ * Interactive Buffer
+ *
+ * @see self::read()
+ * @var array
+ * @access private
+ */
+ var $interactiveBuffer = '';
+
+ /**
+ * Current log size
+ *
+ * Should never exceed self::LOG_MAX_SIZE
+ *
+ * @see self::_send_binary_packet()
+ * @see self::_get_binary_packet()
+ * @var int
+ * @access private
+ */
+ var $log_size;
+
+ /**
+ * Timeout
+ *
+ * @see self::setTimeout()
+ * @access private
+ */
+ var $timeout;
+
+ /**
+ * Current Timeout
+ *
+ * @see self::_get_channel_packet()
+ * @access private
+ */
+ var $curTimeout;
+
+ /**
+ * Real-time log file pointer
+ *
+ * @see self::_append_log()
+ * @var resource
+ * @access private
+ */
+ var $realtime_log_file;
+
+ /**
+ * Real-time log file size
+ *
+ * @see self::_append_log()
+ * @var int
+ * @access private
+ */
+ var $realtime_log_size;
+
+ /**
+ * Has the signature been validated?
+ *
+ * @see self::getServerPublicHostKey()
+ * @var bool
+ * @access private
+ */
+ var $signature_validated = false;
+
+ /**
+ * Real-time log file wrap boolean
+ *
+ * @see self::_append_log()
+ * @access private
+ */
+ var $realtime_log_wrap;
+
+ /**
+ * Flag to suppress stderr from output
+ *
+ * @see self::enableQuietMode()
+ * @access private
+ */
+ var $quiet_mode = false;
+
+ /**
+ * Time of first network activity
+ *
+ * @var int
+ * @access private
+ */
+ var $last_packet;
+
+ /**
+ * Exit status returned from ssh if any
+ *
+ * @var int
+ * @access private
+ */
+ var $exit_status;
+
+ /**
+ * Flag to request a PTY when using exec()
+ *
+ * @var bool
+ * @see self::enablePTY()
+ * @access private
+ */
+ var $request_pty = false;
+
+ /**
+ * Flag set while exec() is running when using enablePTY()
+ *
+ * @var bool
+ * @access private
+ */
+ var $in_request_pty_exec = false;
+
+ /**
+ * Flag set after startSubsystem() is called
+ *
+ * @var bool
+ * @access private
+ */
+ var $in_subsystem;
+
+ /**
+ * Contents of stdError
+ *
+ * @var string
+ * @access private
+ */
+ var $stdErrorLog;
+
+ /**
+ * The Last Interactive Response
+ *
+ * @see self::_keyboard_interactive_process()
+ * @var string
+ * @access private
+ */
+ var $last_interactive_response = '';
+
+ /**
+ * Keyboard Interactive Request / Responses
+ *
+ * @see self::_keyboard_interactive_process()
+ * @var array
+ * @access private
+ */
+ var $keyboard_requests_responses = array();
+
+ /**
+ * Banner Message
+ *
+ * Quoting from the RFC, "in some jurisdictions, sending a warning message before
+ * authentication may be relevant for getting legal protection."
+ *
+ * @see self::_filter()
+ * @see self::getBannerMessage()
+ * @var string
+ * @access private
+ */
+ var $banner_message = '';
+
+ /**
+ * Did read() timeout or return normally?
+ *
+ * @see self::isTimeout()
+ * @var bool
+ * @access private
+ */
+ var $is_timeout = false;
+
+ /**
+ * Log Boundary
+ *
+ * @see self::_format_log()
+ * @var string
+ * @access private
+ */
+ var $log_boundary = ':';
+
+ /**
+ * Log Long Width
+ *
+ * @see self::_format_log()
+ * @var int
+ * @access private
+ */
+ var $log_long_width = 65;
+
+ /**
+ * Log Short Width
+ *
+ * @see self::_format_log()
+ * @var int
+ * @access private
+ */
+ var $log_short_width = 16;
+
+ /**
+ * Hostname
+ *
+ * @see self::__construct()
+ * @see self::_connect()
+ * @var string
+ * @access private
+ */
+ var $host;
+
+ /**
+ * Port Number
+ *
+ * @see self::__construct()
+ * @see self::_connect()
+ * @var int
+ * @access private
+ */
+ var $port;
+
+ /**
+ * Number of columns for terminal window size
+ *
+ * @see self::getWindowColumns()
+ * @see self::setWindowColumns()
+ * @see self::setWindowSize()
+ * @var int
+ * @access private
+ */
+ var $windowColumns = 80;
+
+ /**
+ * Number of columns for terminal window size
+ *
+ * @see self::getWindowRows()
+ * @see self::setWindowRows()
+ * @see self::setWindowSize()
+ * @var int
+ * @access private
+ */
+ var $windowRows = 24;
+
+ /**
+ * Crypto Engine
+ *
+ * @see self::setCryptoEngine()
+ * @see self::_key_exchange()
+ * @var int
+ * @access private
+ */
+ var $crypto_engine = false;
+
+ /**
+ * A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
+ *
+ * @var System_SSH_Agent
+ * @access private
+ */
+ var $agent;
+
+ /**
+ * Send the identification string first?
+ *
+ * @var bool
+ * @access private
+ */
+ var $send_id_string_first = true;
+
+ /**
+ * Send the key exchange initiation packet first?
+ *
+ * @var bool
+ * @access private
+ */
+ var $send_kex_first = true;
+
+ /**
+ * Some versions of OpenSSH incorrectly calculate the key size
+ *
+ * @var bool
+ * @access private
+ */
+ var $bad_key_size_fix = false;
+
+ /**
+ * The selected decryption algorithm
+ *
+ * @var string
+ * @access private
+ */
+ var $decrypt_algorithm = '';
+
+ /**
+ * Should we try to re-connect to re-establish keys?
+ *
+ * @var bool
+ * @access private
+ */
+ var $retry_connect = false;
+
+ /**
+ * Binary Packet Buffer
+ *
+ * @var string|false
+ * @access private
+ */
+ var $binary_packet_buffer = false;
+
+ /**
+ * Preferred Signature Format
+ *
+ * @var string|false
+ * @access private
+ */
+ var $preferred_signature_format = false;
+
+ /**
+ * Authentication Credentials
+ *
+ * @var array
+ * @access private
+ */
+ var $auth = array();
+
+ /**
+ * Default Constructor.
+ *
+ * $host can either be a string, representing the host, or a stream resource.
+ *
+ * @param mixed $host
+ * @param int $port
+ * @param int $timeout
+ * @see self::login()
+ * @return \phpseclib\Net\SSH2
+ * @access public
+ */
+ function __construct($host, $port = 22, $timeout = 10)
+ {
+ $this->message_numbers = array(
+ 1 => 'NET_SSH2_MSG_DISCONNECT',
+ 2 => 'NET_SSH2_MSG_IGNORE',
+ 3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
+ 4 => 'NET_SSH2_MSG_DEBUG',
+ 5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
+ 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
+ 20 => 'NET_SSH2_MSG_KEXINIT',
+ 21 => 'NET_SSH2_MSG_NEWKEYS',
+ 30 => 'NET_SSH2_MSG_KEXDH_INIT',
+ 31 => 'NET_SSH2_MSG_KEXDH_REPLY',
+ 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
+ 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
+ 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
+ 53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
+
+ 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
+ 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
+ 82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
+ 90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
+ 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
+ 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
+ 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
+ 94 => 'NET_SSH2_MSG_CHANNEL_DATA',
+ 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
+ 96 => 'NET_SSH2_MSG_CHANNEL_EOF',
+ 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
+ 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
+ 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
+ 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
+ );
+ $this->disconnect_reasons = array(
+ 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
+ 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
+ 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
+ 4 => 'NET_SSH2_DISCONNECT_RESERVED',
+ 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
+ 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
+ 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
+ 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
+ 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
+ 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
+ 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
+ 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
+ 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
+ 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
+ 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
+ );
+ $this->channel_open_failure_reasons = array(
+ 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
+ );
+ $this->terminal_modes = array(
+ 0 => 'NET_SSH2_TTY_OP_END'
+ );
+ $this->channel_extended_data_type_codes = array(
+ 1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
+ );
+
+ $this->_define_array(
+ $this->message_numbers,
+ $this->disconnect_reasons,
+ $this->channel_open_failure_reasons,
+ $this->terminal_modes,
+ $this->channel_extended_data_type_codes,
+ array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'),
+ array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'),
+ array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
+ 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'),
+ // RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
+ array(30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD',
+ 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
+ 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
+ 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
+ 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'),
+ // RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
+ array(30 => 'NET_SSH2_MSG_KEX_ECDH_INIT',
+ 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY')
+ );
+
+ if (is_resource($host)) {
+ $this->fsock = $host;
+ return;
+ }
+
+ if (is_string($host)) {
+ $this->host = $host;
+ $this->port = $port;
+ $this->timeout = $timeout;
+ }
+ }
+
+ /**
+ * Set Crypto Engine Mode
+ *
+ * Possible $engine values:
+ * CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT
+ *
+ * @param int $engine
+ * @access public
+ */
+ function setCryptoEngine($engine)
+ {
+ $this->crypto_engine = $engine;
+ }
+
+ /**
+ * Send Identification String First
+ *
+ * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
+ * both sides MUST send an identification string". It does not say which side sends it first. In
+ * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
+ *
+ * @access public
+ */
+ function sendIdentificationStringFirst()
+ {
+ $this->send_id_string_first = true;
+ }
+
+ /**
+ * Send Identification String Last
+ *
+ * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
+ * both sides MUST send an identification string". It does not say which side sends it first. In
+ * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
+ *
+ * @access public
+ */
+ function sendIdentificationStringLast()
+ {
+ $this->send_id_string_first = false;
+ }
+
+ /**
+ * Send SSH_MSG_KEXINIT First
+ *
+ * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
+ * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
+ * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
+ *
+ * @access public
+ */
+ function sendKEXINITFirst()
+ {
+ $this->send_kex_first = true;
+ }
+
+ /**
+ * Send SSH_MSG_KEXINIT Last
+ *
+ * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
+ * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
+ * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
+ *
+ * @access public
+ */
+ function sendKEXINITLast()
+ {
+ $this->send_kex_first = false;
+ }
+
+ /**
+ * Connect to an SSHv2 server
+ *
+ * @return bool
+ * @access private
+ */
+ function _connect()
+ {
+ if ($this->bitmap & self::MASK_CONSTRUCTOR) {
+ return false;
+ }
+
+ $this->bitmap |= self::MASK_CONSTRUCTOR;
+
+ $this->curTimeout = $this->timeout;
+
+ $this->last_packet = microtime(true);
+
+ if (!is_resource($this->fsock)) {
+ $start = microtime(true);
+ // with stream_select a timeout of 0 means that no timeout takes place;
+ // with fsockopen a timeout of 0 means that you instantly timeout
+ // to resolve this incompatibility a timeout of 100,000 will be used for fsockopen if timeout is 0
+ $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout);
+ if (!$this->fsock) {
+ $host = $this->host . ':' . $this->port;
+ user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
+ return false;
+ }
+ $elapsed = microtime(true) - $start;
+
+ if ($this->curTimeout) {
+ $this->curTimeout-= $elapsed;
+ if ($this->curTimeout < 0) {
+ $this->is_timeout = true;
+ return false;
+ }
+ }
+ }
+
+ $this->identifier = $this->_generate_identifier();
+
+ if ($this->send_id_string_first) {
+ fputs($this->fsock, $this->identifier . "\r\n");
+ }
+
+ /* According to the SSH2 specs,
+
+ "The server MAY send other lines of data before sending the version
+ string. Each line SHOULD be terminated by a Carriage Return and Line
+ Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
+ in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients
+ MUST be able to process such lines." */
+ $data = '';
+ while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(\d\.\d+).*)#ms', $data, $matches)) {
+ $line = '';
+ while (true) {
+ if ($this->curTimeout) {
+ if ($this->curTimeout < 0) {
+ $this->is_timeout = true;
+ return false;
+ }
+ $read = array($this->fsock);
+ $write = $except = null;
+ $start = microtime(true);
+ $sec = floor($this->curTimeout);
+ $usec = 1000000 * ($this->curTimeout - $sec);
+ // on windows this returns a "Warning: Invalid CRT parameters detected" error
+ // the !count() is done as a workaround for <https://bugs.php.net/42682>
+ if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
+ $this->is_timeout = true;
+ return false;
+ }
+ $elapsed = microtime(true) - $start;
+ $this->curTimeout-= $elapsed;
+ }
+
+ $temp = stream_get_line($this->fsock, 255, "\n");
+ if (strlen($temp) == 255) {
+ continue;
+ }
+
+ $line.= "$temp\n";
+
+ // quoting RFC4253, "Implementers who wish to maintain
+ // compatibility with older, undocumented versions of this protocol may
+ // want to process the identification string without expecting the
+ // presence of the carriage return character for reasons described in
+ // Section 5 of this document."
+
+ //if (substr($line, -2) == "\r\n") {
+ // break;
+ //}
+
+ break;
+ }
+
+ $data.= $line;
+ }
+
+ if (feof($this->fsock)) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ $extra = $matches[1];
+
+ if (defined('NET_SSH2_LOGGING')) {
+ $this->_append_log('<-', $matches[0]);
+ $this->_append_log('->', $this->identifier . "\r\n");
+ }
+
+ $this->server_identifier = trim($temp, "\r\n");
+ if (strlen($extra)) {
+ $this->errors[] = $data;
+ }
+
+ if (version_compare($matches[3], '1.99', '<')) {
+ user_error("Cannot connect to SSH $matches[3] servers");
+ return false;
+ }
+
+ if (!$this->send_id_string_first) {
+ fputs($this->fsock, $this->identifier . "\r\n");
+ }
+
+ if (!$this->send_kex_first) {
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
+ user_error('Expected SSH_MSG_KEXINIT');
+ return false;
+ }
+
+ if (!$this->_key_exchange($response)) {
+ return false;
+ }
+ }
+
+ if ($this->send_kex_first && !$this->_key_exchange()) {
+ return false;
+ }
+
+ $this->bitmap|= self::MASK_CONNECTED;
+
+ return true;
+ }
+
+ /**
+ * Generates the SSH identifier
+ *
+ * You should overwrite this method in your own class if you want to use another identifier
+ *
+ * @access protected
+ * @return string
+ */
+ function _generate_identifier()
+ {
+ $identifier = 'SSH-2.0-phpseclib_2.0';
+
+ $ext = array();
+ if (function_exists('\\Sodium\\library_version_major')) {
+ $ext[] = 'libsodium';
+ }
+
+ if (extension_loaded('openssl')) {
+ $ext[] = 'openssl';
+ } elseif (extension_loaded('mcrypt')) {
+ $ext[] = 'mcrypt';
+ }
+
+ if (extension_loaded('gmp')) {
+ $ext[] = 'gmp';
+ } elseif (extension_loaded('bcmath')) {
+ $ext[] = 'bcmath';
+ }
+
+ if (!empty($ext)) {
+ $identifier .= ' (' . implode(', ', $ext) . ')';
+ }
+
+ return $identifier;
+ }
+
+ /**
+ * Key Exchange
+ *
+ * @param string $kexinit_payload_server optional
+ * @access private
+ */
+ function _key_exchange($kexinit_payload_server = false)
+ {
+ $kex_algorithms = array(
+ // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
+ // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
+ // libssh repository for more information.
+ 'curve25519-sha256@libssh.org',
+
+ // Diffie-Hellman Key Agreement (DH) using integer modulo prime
+ // groups.
+ 'diffie-hellman-group1-sha1', // REQUIRED
+ 'diffie-hellman-group14-sha1', // REQUIRED
+ 'diffie-hellman-group-exchange-sha1', // RFC 4419
+ 'diffie-hellman-group-exchange-sha256', // RFC 4419
+ );
+ if (!function_exists('\\Sodium\\library_version_major')) {
+ $kex_algorithms = array_diff(
+ $kex_algorithms,
+ array('curve25519-sha256@libssh.org')
+ );
+ }
+
+ $server_host_key_algorithms = array(
+ 'rsa-sha2-256', // RFC 8332
+ 'rsa-sha2-512', // RFC 8332
+ 'ssh-rsa', // RECOMMENDED sign Raw RSA Key
+ 'ssh-dss' // REQUIRED sign Raw DSS Key
+ );
+
+ $encryption_algorithms = array(
+ // from <http://tools.ietf.org/html/rfc4345#section-4>:
+ 'arcfour256',
+ 'arcfour128',
+
+ //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
+
+ // CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
+ 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
+ 'aes192-ctr', // RECOMMENDED AES with 192-bit key
+ 'aes256-ctr', // RECOMMENDED AES with 256-bit key
+
+ 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
+ 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
+ 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
+
+ 'aes128-cbc', // RECOMMENDED AES with a 128-bit key
+ 'aes192-cbc', // OPTIONAL AES with a 192-bit key
+ 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
+
+ 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key
+ 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key
+ 'twofish256-cbc',
+ 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc"
+ // (this is being retained for historical reasons)
+
+ 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode
+
+ 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode
+
+ '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
+
+ '3des-cbc', // REQUIRED three-key 3DES in CBC mode
+ //'none' // OPTIONAL no encryption; NOT RECOMMENDED
+ );
+
+ if (extension_loaded('openssl') && !extension_loaded('mcrypt')) {
+ // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to
+ // instances that do not use continuous buffers
+ $encryption_algorithms = array_diff(
+ $encryption_algorithms,
+ array('arcfour256', 'arcfour128', 'arcfour')
+ );
+ }
+
+ if (class_exists('\phpseclib\Crypt\RC4') === false) {
+ $encryption_algorithms = array_diff(
+ $encryption_algorithms,
+ array('arcfour256', 'arcfour128', 'arcfour')
+ );
+ }
+ if (class_exists('\phpseclib\Crypt\Rijndael') === false) {
+ $encryption_algorithms = array_diff(
+ $encryption_algorithms,
+ array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc')
+ );
+ }
+ if (class_exists('\phpseclib\Crypt\Twofish') === false) {
+ $encryption_algorithms = array_diff(
+ $encryption_algorithms,
+ array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc')
+ );
+ }
+ if (class_exists('\phpseclib\Crypt\Blowfish') === false) {
+ $encryption_algorithms = array_diff(
+ $encryption_algorithms,
+ array('blowfish-ctr', 'blowfish-cbc')
+ );
+ }
+ if (class_exists('\phpseclib\Crypt\TripleDES') === false) {
+ $encryption_algorithms = array_diff(
+ $encryption_algorithms,
+ array('3des-ctr', '3des-cbc')
+ );
+ }
+ $encryption_algorithms = array_values($encryption_algorithms);
+
+ $mac_algorithms = array(
+ // from <http://www.ietf.org/rfc/rfc6668.txt>:
+ 'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32)
+
+ 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
+ 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
+ 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
+ 'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
+ //'none' // OPTIONAL no MAC; NOT RECOMMENDED
+ );
+
+ $compression_algorithms = array(
+ 'none' // REQUIRED no compression
+ //'zlib' // OPTIONAL ZLIB (LZ77) compression
+ );
+
+ // some SSH servers have buggy implementations of some of the above algorithms
+ switch (true) {
+ case $this->server_identifier == 'SSH-2.0-SSHD':
+ case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
+ $mac_algorithms = array_values(array_diff(
+ $mac_algorithms,
+ array('hmac-sha1-96', 'hmac-md5-96')
+ ));
+ }
+
+ $str_kex_algorithms = implode(',', $kex_algorithms);
+ $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
+ $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
+ $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
+ $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
+
+ $client_cookie = Random::string(16);
+
+ $kexinit_payload_client = pack(
+ 'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
+ NET_SSH2_MSG_KEXINIT,
+ $client_cookie,
+ strlen($str_kex_algorithms),
+ $str_kex_algorithms,
+ strlen($str_server_host_key_algorithms),
+ $str_server_host_key_algorithms,
+ strlen($encryption_algorithms_client_to_server),
+ $encryption_algorithms_client_to_server,
+ strlen($encryption_algorithms_server_to_client),
+ $encryption_algorithms_server_to_client,
+ strlen($mac_algorithms_client_to_server),
+ $mac_algorithms_client_to_server,
+ strlen($mac_algorithms_server_to_client),
+ $mac_algorithms_server_to_client,
+ strlen($compression_algorithms_client_to_server),
+ $compression_algorithms_client_to_server,
+ strlen($compression_algorithms_server_to_client),
+ $compression_algorithms_server_to_client,
+ 0,
+ '',
+ 0,
+ '',
+ 0,
+ 0
+ );
+
+ if ($this->send_kex_first) {
+ if (!$this->_send_binary_packet($kexinit_payload_client)) {
+ return false;
+ }
+
+ $kexinit_payload_server = $this->_get_binary_packet();
+ if ($kexinit_payload_server === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
+ user_error('Expected SSH_MSG_KEXINIT');
+ return false;
+ }
+ }
+
+ $response = $kexinit_payload_server;
+ $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
+ $server_cookie = $this->_string_shift($response, 16);
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
+ $first_kex_packet_follows = $first_kex_packet_follows != 0;
+
+ if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) {
+ return false;
+ }
+
+ // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
+ // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
+ // diffie-hellman key exchange as fast as possible
+ $decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
+ $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
+ if ($decryptKeyLength === null) {
+ user_error('No compatible server to client encryption algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
+ $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
+ if ($encryptKeyLength === null) {
+ user_error('No compatible client to server encryption algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ // through diffie-hellman key exchange a symmetric key is obtained
+ $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
+ if ($kex_algorithm === false) {
+ user_error('No compatible key exchange algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
+ $exchange_hash_rfc4419 = '';
+
+ if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
+ $x = Random::string(32);
+ $eBytes = \Sodium\crypto_box_publickey_from_secretkey($x);
+ $clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT;
+ $serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY;
+ $kexHash = new Hash('sha256');
+ } else {
+ if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
+ $dh_group_sizes_packed = pack(
+ 'NNN',
+ $this->kex_dh_group_size_min,
+ $this->kex_dh_group_size_preferred,
+ $this->kex_dh_group_size_max
+ );
+ $packet = pack(
+ 'Ca*',
+ NET_SSH2_MSG_KEXDH_GEX_REQUEST,
+ $dh_group_sizes_packed
+ );
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+ if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
+ user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
+ $primeBytes = $this->_string_shift($response, $primeLength);
+ $prime = new BigInteger($primeBytes, -256);
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('NgLength', $this->_string_shift($response, 4)));
+ $gBytes = $this->_string_shift($response, $gLength);
+ $g = new BigInteger($gBytes, -256);
+
+ $exchange_hash_rfc4419 = pack(
+ 'a*Na*Na*',
+ $dh_group_sizes_packed,
+ $primeLength,
+ $primeBytes,
+ $gLength,
+ $gBytes
+ );
+
+ $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
+ $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
+ } else {
+ switch ($kex_algorithm) {
+ // see http://tools.ietf.org/html/rfc2409#section-6.2 and
+ // http://tools.ietf.org/html/rfc2412, appendex E
+ case 'diffie-hellman-group1-sha1':
+ $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
+ '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
+ '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
+ 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
+ break;
+ // see http://tools.ietf.org/html/rfc3526#section-3
+ case 'diffie-hellman-group14-sha1':
+ $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
+ '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
+ '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
+ 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
+ '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
+ '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
+ 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
+ '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
+ break;
+ }
+ // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
+ // the generator field element is 2 (decimal) and the hash function is sha1.
+ $g = new BigInteger(2);
+ $prime = new BigInteger($prime, 16);
+ $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
+ $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
+ }
+
+ switch ($kex_algorithm) {
+ case 'diffie-hellman-group-exchange-sha256':
+ $kexHash = new Hash('sha256');
+ break;
+ default:
+ $kexHash = new Hash('sha1');
+ }
+
+ /* To increase the speed of the key exchange, both client and server may
+ reduce the size of their private exponents. It should be at least
+ twice as long as the key material that is generated from the shared
+ secret. For more details, see the paper by van Oorschot and Wiener
+ [VAN-OORSCHOT].
+
+ -- http://tools.ietf.org/html/rfc4419#section-6.2 */
+ $one = new BigInteger(1);
+ $keyLength = min($kexHash->getLength(), max($encryptKeyLength, $decryptKeyLength));
+ $max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
+ $max = $max->subtract($one);
+
+ $x = $one->random($one, $max);
+ $e = $g->modPow($x, $prime);
+
+ $eBytes = $e->toBytes(true);
+ }
+ $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
+
+ if (!$this->_send_binary_packet($data)) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ if ($type != $serverKexReplyMessage) {
+ user_error('Expected SSH_MSG_KEXDH_REPLY');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $fBytes = $this->_string_shift($response, $temp['length']);
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($response, 4));
+ $this->signature = $this->_string_shift($response, $temp['length']);
+
+ if (strlen($this->signature) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
+ $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
+
+ if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
+ if (strlen($fBytes) !== 32) {
+ user_error('Received curve25519 public key of invalid length.');
+ return false;
+ }
+ $key = new BigInteger(\Sodium\crypto_scalarmult($x, $fBytes), 256);
+ \Sodium\memzero($x);
+ } else {
+ $f = new BigInteger($fBytes, -256);
+ $key = $f->modPow($x, $prime);
+ }
+ $keyBytes = $key->toBytes(true);
+
+ $this->exchange_hash = pack(
+ 'Na*Na*Na*Na*Na*a*Na*Na*Na*',
+ strlen($this->identifier),
+ $this->identifier,
+ strlen($this->server_identifier),
+ $this->server_identifier,
+ strlen($kexinit_payload_client),
+ $kexinit_payload_client,
+ strlen($kexinit_payload_server),
+ $kexinit_payload_server,
+ strlen($this->server_public_host_key),
+ $this->server_public_host_key,
+ $exchange_hash_rfc4419,
+ strlen($eBytes),
+ $eBytes,
+ strlen($fBytes),
+ $fBytes,
+ strlen($keyBytes),
+ $keyBytes
+ );
+
+ $this->exchange_hash = $kexHash->hash($this->exchange_hash);
+
+ if ($this->session_id === false) {
+ $this->session_id = $this->exchange_hash;
+ }
+
+ $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
+ if ($server_host_key_algorithm === false) {
+ user_error('No compatible server host key algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ switch ($server_host_key_algorithm) {
+ case 'ssh-dss':
+ $expected_key_format = 'ssh-dss';
+ break;
+ //case 'rsa-sha2-256':
+ //case 'rsa-sha2-512':
+ //case 'ssh-rsa':
+ default:
+ $expected_key_format = 'ssh-rsa';
+ }
+
+ if ($public_key_format != $expected_key_format || $this->signature_format != $server_host_key_algorithm) {
+ switch (true) {
+ case $this->signature_format == $server_host_key_algorithm:
+ case $server_host_key_algorithm != 'rsa-sha2-256' && $server_host_key_algorithm != 'rsa-sha2-512':
+ case $this->signature_format != 'ssh-rsa':
+ user_error('Server Host Key Algorithm Mismatch');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+ }
+
+ $packet = pack(
+ 'C',
+ NET_SSH2_MSG_NEWKEYS
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ if ($type != NET_SSH2_MSG_NEWKEYS) {
+ user_error('Expected SSH_MSG_NEWKEYS');
+ return false;
+ }
+
+ $this->decrypt_algorithm = $decrypt;
+
+ $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
+
+ $this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt);
+ if ($this->encrypt) {
+ if ($this->crypto_engine) {
+ $this->encrypt->setPreferredEngine($this->crypto_engine);
+ }
+ if ($this->encrypt->block_size) {
+ $this->encrypt_block_size = $this->encrypt->block_size;
+ }
+ $this->encrypt->enableContinuousBuffer();
+ $this->encrypt->disablePadding();
+
+ $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
+ while ($this->encrypt_block_size > strlen($iv)) {
+ $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
+ }
+ $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
+
+ $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
+ while ($encryptKeyLength > strlen($key)) {
+ $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
+ }
+ $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
+ }
+
+ $this->decrypt = $this->_encryption_algorithm_to_crypt_instance($decrypt);
+ if ($this->decrypt) {
+ if ($this->crypto_engine) {
+ $this->decrypt->setPreferredEngine($this->crypto_engine);
+ }
+ if ($this->decrypt->block_size) {
+ $this->decrypt_block_size = $this->decrypt->block_size;
+ }
+ $this->decrypt->enableContinuousBuffer();
+ $this->decrypt->disablePadding();
+
+ $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
+ while ($this->decrypt_block_size > strlen($iv)) {
+ $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
+ }
+ $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
+
+ $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
+ while ($decryptKeyLength > strlen($key)) {
+ $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
+ }
+ $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
+ }
+
+ /* The "arcfour128" algorithm is the RC4 cipher, as described in
+ [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream
+ generated by the cipher MUST be discarded, and the first byte of the
+ first encrypted packet MUST be encrypted using the 1537th byte of
+ keystream.
+
+ -- http://tools.ietf.org/html/rfc4345#section-4 */
+ if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') {
+ $this->encrypt->encrypt(str_repeat("\0", 1536));
+ }
+ if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') {
+ $this->decrypt->decrypt(str_repeat("\0", 1536));
+ }
+
+ $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
+ if ($mac_algorithm === false) {
+ user_error('No compatible client to server message authentication algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $createKeyLength = 0; // ie. $mac_algorithm == 'none'
+ switch ($mac_algorithm) {
+ case 'hmac-sha2-256':
+ $this->hmac_create = new Hash('sha256');
+ $createKeyLength = 32;
+ break;
+ case 'hmac-sha1':
+ $this->hmac_create = new Hash('sha1');
+ $createKeyLength = 20;
+ break;
+ case 'hmac-sha1-96':
+ $this->hmac_create = new Hash('sha1-96');
+ $createKeyLength = 20;
+ break;
+ case 'hmac-md5':
+ $this->hmac_create = new Hash('md5');
+ $createKeyLength = 16;
+ break;
+ case 'hmac-md5-96':
+ $this->hmac_create = new Hash('md5-96');
+ $createKeyLength = 16;
+ }
+
+ $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
+ if ($mac_algorithm === false) {
+ user_error('No compatible server to client message authentication algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $checkKeyLength = 0;
+ $this->hmac_size = 0;
+ switch ($mac_algorithm) {
+ case 'hmac-sha2-256':
+ $this->hmac_check = new Hash('sha256');
+ $checkKeyLength = 32;
+ $this->hmac_size = 32;
+ break;
+ case 'hmac-sha1':
+ $this->hmac_check = new Hash('sha1');
+ $checkKeyLength = 20;
+ $this->hmac_size = 20;
+ break;
+ case 'hmac-sha1-96':
+ $this->hmac_check = new Hash('sha1-96');
+ $checkKeyLength = 20;
+ $this->hmac_size = 12;
+ break;
+ case 'hmac-md5':
+ $this->hmac_check = new Hash('md5');
+ $checkKeyLength = 16;
+ $this->hmac_size = 16;
+ break;
+ case 'hmac-md5-96':
+ $this->hmac_check = new Hash('md5-96');
+ $checkKeyLength = 16;
+ $this->hmac_size = 12;
+ }
+
+ $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
+ while ($createKeyLength > strlen($key)) {
+ $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
+ }
+ $this->hmac_create->setKey(substr($key, 0, $createKeyLength));
+
+ $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id);
+ while ($checkKeyLength > strlen($key)) {
+ $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
+ }
+ $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
+
+ $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
+ if ($compression_algorithm === false) {
+ user_error('No compatible server to client compression algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+ $this->decompress = $compression_algorithm == 'zlib';
+
+ $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
+ if ($compression_algorithm === false) {
+ user_error('No compatible client to server compression algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+ $this->compress = $compression_algorithm == 'zlib';
+
+ return true;
+ }
+
+ /**
+ * Maps an encryption algorithm name to the number of key bytes.
+ *
+ * @param string $algorithm Name of the encryption algorithm
+ * @return int|null Number of bytes as an integer or null for unknown
+ * @access private
+ */
+ function _encryption_algorithm_to_key_size($algorithm)
+ {
+ if ($this->bad_key_size_fix && $this->_bad_algorithm_candidate($algorithm)) {
+ return 16;
+ }
+
+ switch ($algorithm) {
+ case 'none':
+ return 0;
+ case 'aes128-cbc':
+ case 'aes128-ctr':
+ case 'arcfour':
+ case 'arcfour128':
+ case 'blowfish-cbc':
+ case 'blowfish-ctr':
+ case 'twofish128-cbc':
+ case 'twofish128-ctr':
+ return 16;
+ case '3des-cbc':
+ case '3des-ctr':
+ case 'aes192-cbc':
+ case 'aes192-ctr':
+ case 'twofish192-cbc':
+ case 'twofish192-ctr':
+ return 24;
+ case 'aes256-cbc':
+ case 'aes256-ctr':
+ case 'arcfour256':
+ case 'twofish-cbc':
+ case 'twofish256-cbc':
+ case 'twofish256-ctr':
+ return 32;
+ }
+ return null;
+ }
+
+ /**
+ * Maps an encryption algorithm name to an instance of a subclass of
+ * \phpseclib\Crypt\Base.
+ *
+ * @param string $algorithm Name of the encryption algorithm
+ * @return mixed Instance of \phpseclib\Crypt\Base or null for unknown
+ * @access private
+ */
+ function _encryption_algorithm_to_crypt_instance($algorithm)
+ {
+ switch ($algorithm) {
+ case '3des-cbc':
+ return new TripleDES();
+ case '3des-ctr':
+ return new TripleDES(Base::MODE_CTR);
+ case 'aes256-cbc':
+ case 'aes192-cbc':
+ case 'aes128-cbc':
+ return new Rijndael();
+ case 'aes256-ctr':
+ case 'aes192-ctr':
+ case 'aes128-ctr':
+ return new Rijndael(Base::MODE_CTR);
+ case 'blowfish-cbc':
+ return new Blowfish();
+ case 'blowfish-ctr':
+ return new Blowfish(Base::MODE_CTR);
+ case 'twofish128-cbc':
+ case 'twofish192-cbc':
+ case 'twofish256-cbc':
+ case 'twofish-cbc':
+ return new Twofish();
+ case 'twofish128-ctr':
+ case 'twofish192-ctr':
+ case 'twofish256-ctr':
+ return new Twofish(Base::MODE_CTR);
+ case 'arcfour':
+ case 'arcfour128':
+ case 'arcfour256':
+ return new RC4();
+ }
+ return null;
+ }
+
+ /*
+ * Tests whether or not proposed algorithm has a potential for issues
+ *
+ * @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html
+ * @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291
+ * @param string $algorithm Name of the encryption algorithm
+ * @return bool
+ * @access private
+ */
+ function _bad_algorithm_candidate($algorithm)
+ {
+ switch ($algorithm) {
+ case 'arcfour256':
+ case 'aes192-ctr':
+ case 'aes256-ctr':
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Login
+ *
+ * The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array
+ *
+ * @param string $username
+ * @param mixed $password
+ * @param mixed $...
+ * @return bool
+ * @see self::_login()
+ * @access public
+ */
+ function login($username)
+ {
+ $args = func_get_args();
+ $this->auth[] = $args;
+ return call_user_func_array(array(&$this, '_login'), $args);
+ }
+
+ /**
+ * Login Helper
+ *
+ * @param string $username
+ * @param mixed $password
+ * @param mixed $...
+ * @return bool
+ * @see self::_login_helper()
+ * @access private
+ */
+ function _login($username)
+ {
+ if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
+ if (!$this->_connect()) {
+ return false;
+ }
+ }
+
+ $args = array_slice(func_get_args(), 1);
+ if (empty($args)) {
+ return $this->_login_helper($username);
+ }
+
+ foreach ($args as $arg) {
+ if ($this->_login_helper($username, $arg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Login Helper
+ *
+ * @param string $username
+ * @param string $password
+ * @return bool
+ * @access private
+ * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
+ * by sending dummy SSH_MSG_IGNORE messages.
+ */
+ function _login_helper($username, $password = null)
+ {
+ if (!($this->bitmap & self::MASK_CONNECTED)) {
+ return false;
+ }
+
+ if (!($this->bitmap & self::MASK_LOGIN_REQ)) {
+ $packet = pack(
+ 'CNa*',
+ NET_SSH2_MSG_SERVICE_REQUEST,
+ strlen('ssh-userauth'),
+ 'ssh-userauth'
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ if ($this->retry_connect) {
+ $this->retry_connect = false;
+ if (!$this->_connect()) {
+ return false;
+ }
+ return $this->_login_helper($username, $password);
+ }
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
+ user_error('Expected SSH_MSG_SERVICE_ACCEPT');
+ return false;
+ }
+ $this->bitmap |= self::MASK_LOGIN_REQ;
+ }
+
+ if (strlen($this->last_interactive_response)) {
+ return !is_string($password) && !is_array($password) ? false : $this->_keyboard_interactive_process($password);
+ }
+
+ if ($password instanceof RSA) {
+ return $this->_privatekey_login($username, $password);
+ } elseif ($password instanceof Agent) {
+ return $this->_ssh_agent_login($username, $password);
+ }
+
+ if (is_array($password)) {
+ if ($this->_keyboard_interactive_login($username, $password)) {
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ }
+ return false;
+ }
+
+ if (!isset($password)) {
+ $packet = pack(
+ 'CNa*Na*Na*',
+ NET_SSH2_MSG_USERAUTH_REQUEST,
+ strlen($username),
+ $username,
+ strlen('ssh-connection'),
+ 'ssh-connection',
+ strlen('none'),
+ 'none'
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ switch ($type) {
+ case NET_SSH2_MSG_USERAUTH_SUCCESS:
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ //case NET_SSH2_MSG_USERAUTH_FAILURE:
+ default:
+ return false;
+ }
+ }
+
+ $packet = pack(
+ 'CNa*Na*Na*CNa*',
+ NET_SSH2_MSG_USERAUTH_REQUEST,
+ strlen($username),
+ $username,
+ strlen('ssh-connection'),
+ 'ssh-connection',
+ strlen('password'),
+ 'password',
+ 0,
+ strlen($password),
+ $password
+ );
+
+ // remove the username and password from the logged packet
+ if (!defined('NET_SSH2_LOGGING')) {
+ $logged = null;
+ } else {
+ $logged = pack(
+ 'CNa*Na*Na*CNa*',
+ NET_SSH2_MSG_USERAUTH_REQUEST,
+ strlen('username'),
+ 'username',
+ strlen('ssh-connection'),
+ 'ssh-connection',
+ strlen('password'),
+ 'password',
+ 0,
+ strlen('password'),
+ 'password'
+ );
+ }
+
+ if (!$this->_send_binary_packet($packet, $logged)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ switch ($type) {
+ case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // in theory, the password can be changed
+ if (defined('NET_SSH2_LOGGING')) {
+ $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ';
+ }
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . $this->_string_shift($response, $length);
+ return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
+ case NET_SSH2_MSG_USERAUTH_FAILURE:
+ // can we use keyboard-interactive authentication? if not then either the login is bad or the server employees
+ // multi-factor authentication
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $auth_methods = explode(',', $this->_string_shift($response, $length));
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Cpartial_success', $this->_string_shift($response, 1)));
+ $partial_success = $partial_success != 0;
+
+ if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) {
+ if ($this->_keyboard_interactive_login($username, $password)) {
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ }
+ return false;
+ }
+ return false;
+ case NET_SSH2_MSG_USERAUTH_SUCCESS:
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Login via keyboard-interactive authentication
+ *
+ * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator.
+ *
+ * @param string $username
+ * @param string $password
+ * @return bool
+ * @access private
+ */
+ function _keyboard_interactive_login($username, $password)
+ {
+ $packet = pack(
+ 'CNa*Na*Na*Na*Na*',
+ NET_SSH2_MSG_USERAUTH_REQUEST,
+ strlen($username),
+ $username,
+ strlen('ssh-connection'),
+ 'ssh-connection',
+ strlen('keyboard-interactive'),
+ 'keyboard-interactive',
+ 0,
+ '',
+ 0,
+ ''
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ return $this->_keyboard_interactive_process($password);
+ }
+
+ /**
+ * Handle the keyboard-interactive requests / responses.
+ *
+ * @param string $responses...
+ * @return bool
+ * @access private
+ */
+ function _keyboard_interactive_process()
+ {
+ $responses = func_get_args();
+
+ if (strlen($this->last_interactive_response)) {
+ $response = $this->last_interactive_response;
+ } else {
+ $orig = $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ switch ($type) {
+ case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->_string_shift($response, $length); // name; may be empty
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->_string_shift($response, $length); // instruction; may be empty
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->_string_shift($response, $length); // language tag; may be empty
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nnum_prompts', $this->_string_shift($response, 4)));
+
+ for ($i = 0; $i < count($responses); $i++) {
+ if (is_array($responses[$i])) {
+ foreach ($responses[$i] as $key => $value) {
+ $this->keyboard_requests_responses[$key] = $value;
+ }
+ unset($responses[$i]);
+ }
+ }
+ $responses = array_values($responses);
+
+ if (isset($this->keyboard_requests_responses)) {
+ for ($i = 0; $i < $num_prompts; $i++) {
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ // prompt - ie. "Password: "; must not be empty
+ $prompt = $this->_string_shift($response, $length);
+ //$echo = $this->_string_shift($response) != chr(0);
+ foreach ($this->keyboard_requests_responses as $key => $value) {
+ if (substr($prompt, 0, strlen($key)) == $key) {
+ $responses[] = $value;
+ break;
+ }
+ }
+ }
+ }
+
+ // see http://tools.ietf.org/html/rfc4256#section-3.2
+ if (strlen($this->last_interactive_response)) {
+ $this->last_interactive_response = '';
+ } elseif (defined('NET_SSH2_LOGGING')) {
+ $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
+ 'UNKNOWN',
+ 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
+ $this->message_number_log[count($this->message_number_log) - 1]
+ );
+ }
+
+ if (!count($responses) && $num_prompts) {
+ $this->last_interactive_response = $orig;
+ return false;
+ }
+
+ /*
+ After obtaining the requested information from the user, the client
+ MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message.
+ */
+ // see http://tools.ietf.org/html/rfc4256#section-3.4
+ $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses));
+ for ($i = 0; $i < count($responses); $i++) {
+ $packet.= pack('Na*', strlen($responses[$i]), $responses[$i]);
+ $logged.= pack('Na*', strlen('dummy-answer'), 'dummy-answer');
+ }
+
+ if (!$this->_send_binary_packet($packet, $logged)) {
+ return false;
+ }
+
+ if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) {
+ $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
+ 'UNKNOWN',
+ 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE',
+ $this->message_number_log[count($this->message_number_log) - 1]
+ );
+ }
+
+ /*
+ After receiving the response, the server MUST send either an
+ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another
+ SSH_MSG_USERAUTH_INFO_REQUEST message.
+ */
+ // maybe phpseclib should force close the connection after x request / responses? unless something like that is done
+ // there could be an infinite loop of request / responses.
+ return $this->_keyboard_interactive_process();
+ case NET_SSH2_MSG_USERAUTH_SUCCESS:
+ return true;
+ case NET_SSH2_MSG_USERAUTH_FAILURE:
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ * Login with an ssh-agent provided key
+ *
+ * @param string $username
+ * @param \phpseclib\System\SSH\Agent $agent
+ * @return bool
+ * @access private
+ */
+ function _ssh_agent_login($username, $agent)
+ {
+ $this->agent = $agent;
+ $keys = $agent->requestIdentities();
+ foreach ($keys as $key) {
+ if ($this->_privatekey_login($username, $key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Login with an RSA private key
+ *
+ * @param string $username
+ * @param \phpseclib\Crypt\RSA $password
+ * @return bool
+ * @access private
+ * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
+ * by sending dummy SSH_MSG_IGNORE messages.
+ */
+ function _privatekey_login($username, $privatekey)
+ {
+ // see http://tools.ietf.org/html/rfc4253#page-15
+ $publickey = $privatekey->getPublicKey(RSA::PUBLIC_FORMAT_RAW);
+ if ($publickey === false) {
+ return false;
+ }
+
+ $publickey = array(
+ 'e' => $publickey['e']->toBytes(true),
+ 'n' => $publickey['n']->toBytes(true)
+ );
+ $publickey = pack(
+ 'Na*Na*Na*',
+ strlen('ssh-rsa'),
+ 'ssh-rsa',
+ strlen($publickey['e']),
+ $publickey['e'],
+ strlen($publickey['n']),
+ $publickey['n']
+ );
+
+ switch ($this->signature_format) {
+ case 'rsa-sha2-512':
+ $hash = 'sha512';
+ $signatureType = 'rsa-sha2-512';
+ break;
+ case 'rsa-sha2-256':
+ $hash = 'sha256';
+ $signatureType = 'rsa-sha2-256';
+ break;
+ //case 'ssh-rsa':
+ default:
+ $hash = 'sha1';
+ $signatureType = 'ssh-rsa';
+ }
+
+ $part1 = pack(
+ 'CNa*Na*Na*',
+ NET_SSH2_MSG_USERAUTH_REQUEST,
+ strlen($username),
+ $username,
+ strlen('ssh-connection'),
+ 'ssh-connection',
+ strlen('publickey'),
+ 'publickey'
+ );
+ $part2 = pack('Na*Na*', strlen($signatureType), $signatureType, strlen($publickey), $publickey);
+
+ $packet = $part1 . chr(0) . $part2;
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ switch ($type) {
+ case NET_SSH2_MSG_USERAUTH_FAILURE:
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
+ return false;
+ case NET_SSH2_MSG_USERAUTH_PK_OK:
+ // we'll just take it on faith that the public key blob and the public key algorithm name are as
+ // they should be
+ if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) {
+ $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
+ 'UNKNOWN',
+ 'NET_SSH2_MSG_USERAUTH_PK_OK',
+ $this->message_number_log[count($this->message_number_log) - 1]
+ );
+ }
+ }
+
+ $packet = $part1 . chr(1) . $part2;
+ $privatekey->setSignatureMode(RSA::SIGNATURE_PKCS1);
+ $privatekey->setHash($hash);
+ $signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet));
+ $signature = pack('Na*Na*', strlen($signatureType), $signatureType, strlen($signature), $signature);
+ $packet.= pack('Na*', strlen($signature), $signature);
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ switch ($type) {
+ case NET_SSH2_MSG_USERAUTH_FAILURE:
+ // either the login is bad or the server employs multi-factor authentication
+ return false;
+ case NET_SSH2_MSG_USERAUTH_SUCCESS:
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Set Timeout
+ *
+ * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
+ * Setting $timeout to false or 0 will mean there is no timeout.
+ *
+ * @param mixed $timeout
+ * @access public
+ */
+ function setTimeout($timeout)
+ {
+ $this->timeout = $this->curTimeout = $timeout;
+ }
+
+ /**
+ * Get the output from stdError
+ *
+ * @access public
+ */
+ function getStdError()
+ {
+ return $this->stdErrorLog;
+ }
+
+ /**
+ * Execute Command
+ *
+ * If $callback is set to false then \phpseclib\Net\SSH2::_get_channel_packet(self::CHANNEL_EXEC) will need to be called manually.
+ * In all likelihood, this is not a feature you want to be taking advantage of.
+ *
+ * @param string $command
+ * @param Callback $callback
+ * @return string
+ * @access public
+ */
+ function exec($command, $callback = null)
+ {
+ $this->curTimeout = $this->timeout;
+ $this->is_timeout = false;
+ $this->stdErrorLog = '';
+
+ if (!$this->isAuthenticated()) {
+ return false;
+ }
+
+ if ($this->in_request_pty_exec) {
+ user_error('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
+ return false;
+ }
+
+ // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
+ // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
+ // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
+ // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
+ $this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size;
+ // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
+ // uses 0x4000, that's what will be used here, as well.
+ $packet_size = 0x4000;
+
+ $packet = pack(
+ 'CNa*N3',
+ NET_SSH2_MSG_CHANNEL_OPEN,
+ strlen('session'),
+ 'session',
+ self::CHANNEL_EXEC,
+ $this->window_size_server_to_client[self::CHANNEL_EXEC],
+ $packet_size
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
+
+ $response = $this->_get_channel_packet(self::CHANNEL_EXEC);
+ if ($response === false) {
+ return false;
+ }
+
+ if ($this->request_pty === true) {
+ $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
+ $packet = pack(
+ 'CNNa*CNa*N5a*',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL_EXEC],
+ strlen('pty-req'),
+ 'pty-req',
+ 1,
+ strlen('vt100'),
+ 'vt100',
+ $this->windowColumns,
+ $this->windowRows,
+ 0,
+ 0,
+ strlen($terminal_modes),
+ $terminal_modes
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ list(, $type) = unpack('C', $this->_string_shift($response, 1));
+
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_SUCCESS:
+ break;
+ case NET_SSH2_MSG_CHANNEL_FAILURE:
+ default:
+ user_error('Unable to request pseudo-terminal');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+ $this->in_request_pty_exec = true;
+ }
+
+ // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things
+ // down. the one place where it might be desirable is if you're doing something like \phpseclib\Net\SSH2::exec('ping localhost &').
+ // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then
+ // then immediately terminate. without such a request exec() will loop indefinitely. the ping process won't end but
+ // neither will your script.
+
+ // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
+ // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
+ // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates.
+ $packet = pack(
+ 'CNNa*CNa*',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL_EXEC],
+ strlen('exec'),
+ 'exec',
+ 1,
+ strlen($command),
+ $command
+ );
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
+
+ $response = $this->_get_channel_packet(self::CHANNEL_EXEC);
+ if ($response === false) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
+
+ if ($callback === false || $this->in_request_pty_exec) {
+ return true;
+ }
+
+ $output = '';
+ while (true) {
+ $temp = $this->_get_channel_packet(self::CHANNEL_EXEC);
+ switch (true) {
+ case $temp === true:
+ return is_callable($callback) ? true : $output;
+ case $temp === false:
+ return false;
+ default:
+ if (is_callable($callback)) {
+ if (call_user_func($callback, $temp) === true) {
+ $this->_close_channel(self::CHANNEL_EXEC);
+ return true;
+ }
+ } else {
+ $output.= $temp;
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates an interactive shell
+ *
+ * @see self::read()
+ * @see self::write()
+ * @return bool
+ * @access private
+ */
+ function _initShell()
+ {
+ if ($this->in_request_pty_exec === true) {
+ return true;
+ }
+
+ $this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size;
+ $packet_size = 0x4000;
+
+ $packet = pack(
+ 'CNa*N3',
+ NET_SSH2_MSG_CHANNEL_OPEN,
+ strlen('session'),
+ 'session',
+ self::CHANNEL_SHELL,
+ $this->window_size_server_to_client[self::CHANNEL_SHELL],
+ $packet_size
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
+
+ $response = $this->_get_channel_packet(self::CHANNEL_SHELL);
+ if ($response === false) {
+ return false;
+ }
+
+ $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
+ $packet = pack(
+ 'CNNa*CNa*N5a*',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL_SHELL],
+ strlen('pty-req'),
+ 'pty-req',
+ 1,
+ strlen('vt100'),
+ 'vt100',
+ $this->windowColumns,
+ $this->windowRows,
+ 0,
+ 0,
+ strlen($terminal_modes),
+ $terminal_modes
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $this->_get_binary_packet();
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+
+ if (!strlen($response)) {
+ return false;
+ }
+ list(, $type) = unpack('C', $this->_string_shift($response, 1));
+
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_SUCCESS:
+ // if a pty can't be opened maybe commands can still be executed
+ case NET_SSH2_MSG_CHANNEL_FAILURE:
+ break;
+ default:
+ user_error('Unable to request pseudo-terminal');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+
+ $packet = pack(
+ 'CNNa*C',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL_SHELL],
+ strlen('shell'),
+ 'shell',
+ 1
+ );
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
+
+ $response = $this->_get_channel_packet(self::CHANNEL_SHELL);
+ if ($response === false) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
+
+ $this->bitmap |= self::MASK_SHELL;
+
+ return true;
+ }
+
+ /**
+ * Return the channel to be used with read() / write()
+ *
+ * @see self::read()
+ * @see self::write()
+ * @return int
+ * @access public
+ */
+ function _get_interactive_channel()
+ {
+ switch (true) {
+ case $this->in_subsystem:
+ return self::CHANNEL_SUBSYSTEM;
+ case $this->in_request_pty_exec:
+ return self::CHANNEL_EXEC;
+ default:
+ return self::CHANNEL_SHELL;
+ }
+ }
+
+ /**
+ * Return an available open channel
+ *
+ * @return int
+ * @access public
+ */
+ function _get_open_channel()
+ {
+ $channel = self::CHANNEL_EXEC;
+ do {
+ if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) {
+ return $channel;
+ }
+ } while ($channel++ < self::CHANNEL_SUBSYSTEM);
+
+ return false;
+ }
+
+ /**
+ * Returns the output of an interactive shell
+ *
+ * Returns when there's a match for $expect, which can take the form of a string literal or,
+ * if $mode == self::READ_REGEX, a regular expression.
+ *
+ * @see self::write()
+ * @param string $expect
+ * @param int $mode
+ * @return string
+ * @access public
+ */
+ function read($expect = '', $mode = self::READ_SIMPLE)
+ {
+ $this->curTimeout = $this->timeout;
+ $this->is_timeout = false;
+
+ if (!$this->isAuthenticated()) {
+ user_error('Operation disallowed prior to login()');
+ return false;
+ }
+
+ if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
+ user_error('Unable to initiate an interactive shell session');
+ return false;
+ }
+
+ $channel = $this->_get_interactive_channel();
+
+ if ($mode == self::READ_NEXT) {
+ return $this->_get_channel_packet($channel);
+ }
+
+ $match = $expect;
+ while (true) {
+ if ($mode == self::READ_REGEX) {
+ preg_match($expect, substr($this->interactiveBuffer, -1024), $matches);
+ $match = isset($matches[0]) ? $matches[0] : '';
+ }
+ $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
+ if ($pos !== false) {
+ return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
+ }
+ $response = $this->_get_channel_packet($channel);
+ if (is_bool($response)) {
+ $this->in_request_pty_exec = false;
+ return $response ? $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer)) : false;
+ }
+
+ $this->interactiveBuffer.= $response;
+ }
+ }
+
+ /**
+ * Inputs a command into an interactive shell.
+ *
+ * @see self::read()
+ * @param string $cmd
+ * @return bool
+ * @access public
+ */
+ function write($cmd)
+ {
+ if (!$this->isAuthenticated()) {
+ user_error('Operation disallowed prior to login()');
+ return false;
+ }
+
+ if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
+ user_error('Unable to initiate an interactive shell session');
+ return false;
+ }
+
+ return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd);
+ }
+
+ /**
+ * Start a subsystem.
+ *
+ * Right now only one subsystem at a time is supported. To support multiple subsystem's stopSubsystem() could accept
+ * a string that contained the name of the subsystem, but at that point, only one subsystem of each type could be opened.
+ * To support multiple subsystem's of the same name maybe it'd be best if startSubsystem() generated a new channel id and
+ * returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented
+ * if there's sufficient demand for such a feature.
+ *
+ * @see self::stopSubsystem()
+ * @param string $subsystem
+ * @return bool
+ * @access public
+ */
+ function startSubsystem($subsystem)
+ {
+ $this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size;
+
+ $packet = pack(
+ 'CNa*N3',
+ NET_SSH2_MSG_CHANNEL_OPEN,
+ strlen('session'),
+ 'session',
+ self::CHANNEL_SUBSYSTEM,
+ $this->window_size,
+ 0x4000
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
+
+ $response = $this->_get_channel_packet(self::CHANNEL_SUBSYSTEM);
+ if ($response === false) {
+ return false;
+ }
+
+ $packet = pack(
+ 'CNNa*CNa*',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $this->server_channels[self::CHANNEL_SUBSYSTEM],
+ strlen('subsystem'),
+ 'subsystem',
+ 1,
+ strlen($subsystem),
+ $subsystem
+ );
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
+
+ $response = $this->_get_channel_packet(self::CHANNEL_SUBSYSTEM);
+
+ if ($response === false) {
+ return false;
+ }
+
+ $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
+
+ $this->bitmap |= self::MASK_SHELL;
+ $this->in_subsystem = true;
+
+ return true;
+ }
+
+ /**
+ * Stops a subsystem.
+ *
+ * @see self::startSubsystem()
+ * @return bool
+ * @access public
+ */
+ function stopSubsystem()
+ {
+ $this->in_subsystem = false;
+ $this->_close_channel(self::CHANNEL_SUBSYSTEM);
+ return true;
+ }
+
+ /**
+ * Closes a channel
+ *
+ * If read() timed out you might want to just close the channel and have it auto-restart on the next read() call
+ *
+ * @access public
+ */
+ function reset()
+ {
+ $this->_close_channel($this->_get_interactive_channel());
+ }
+
+ /**
+ * Is timeout?
+ *
+ * Did exec() or read() return because they timed out or because they encountered the end?
+ *
+ * @access public
+ */
+ function isTimeout()
+ {
+ return $this->is_timeout;
+ }
+
+ /**
+ * Disconnect
+ *
+ * @access public
+ */
+ function disconnect()
+ {
+ $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
+ fclose($this->realtime_log_file);
+ }
+ }
+
+ /**
+ * Destructor.
+ *
+ * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
+ * disconnect().
+ *
+ * @access public
+ */
+ function __destruct()
+ {
+ $this->disconnect();
+ }
+
+ /**
+ * Is the connection still active?
+ *
+ * @return bool
+ * @access public
+ */
+ function isConnected()
+ {
+ return (bool) ($this->bitmap & self::MASK_CONNECTED);
+ }
+
+ /**
+ * Have you successfully been logged in?
+ *
+ * @return bool
+ * @access public
+ */
+ function isAuthenticated()
+ {
+ return (bool) ($this->bitmap & self::MASK_LOGIN);
+ }
+
+ /**
+ * Pings a server connection, or tries to reconnect if the connection has gone down
+ *
+ * Inspired by http://php.net/manual/en/mysqli.ping.php
+ *
+ * @return bool
+ * @access public
+ */
+ function ping()
+ {
+ if (!$this->isAuthenticated()) {
+ return false;
+ }
+
+ $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE] = $this->window_size;
+ $packet_size = 0x4000;
+ $packet = pack(
+ 'CNa*N3',
+ NET_SSH2_MSG_CHANNEL_OPEN,
+ strlen('session'),
+ 'session',
+ self::CHANNEL_KEEP_ALIVE,
+ $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE],
+ $packet_size
+ );
+
+ if (!@$this->_send_binary_packet($packet)) {
+ return $this->_reconnect();
+ }
+
+ $this->channel_status[self::CHANNEL_KEEP_ALIVE] = NET_SSH2_MSG_CHANNEL_OPEN;
+
+ $response = @$this->_get_channel_packet(self::CHANNEL_KEEP_ALIVE);
+ if ($response !== false) {
+ $this->_close_channel(self::CHANNEL_KEEP_ALIVE);
+ return true;
+ }
+
+ return $this->_reconnect();
+ }
+
+ /**
+ * In situ reconnect method
+ *
+ * @return boolean
+ * @access private
+ */
+ function _reconnect()
+ {
+ $this->_reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST);
+ $this->retry_connect = true;
+ if (!$this->_connect()) {
+ return false;
+ }
+ foreach ($this->auth as $auth) {
+ $result = call_user_func_array(array(&$this, 'login'), $auth);
+ }
+ return $result;
+ }
+
+ /**
+ * Resets a connection for re-use
+ *
+ * @param int $reason
+ * @access private
+ */
+ function _reset_connection($reason)
+ {
+ $this->_disconnect($reason);
+ $this->decrypt = $this->encrypt = false;
+ $this->decrypt_block_size = $this->encrypt_block_size = 8;
+ $this->hmac_check = $this->hmac_create = false;
+ $this->hmac_size = false;
+ $this->session_id = false;
+ $this->retry_connect = true;
+ $this->get_seq_no = $this->send_seq_no = 0;
+ }
+
+ /**
+ * Gets Binary Packets
+ *
+ * See '6. Binary Packet Protocol' of rfc4253 for more info.
+ *
+ * @see self::_send_binary_packet()
+ * @return string
+ * @access private
+ */
+ function _get_binary_packet($skip_channel_filter = false)
+ {
+ if (!is_resource($this->fsock) || feof($this->fsock)) {
+ $this->bitmap = 0;
+ user_error('Connection closed prematurely');
+ return false;
+ }
+
+ $start = microtime(true);
+ $raw = stream_get_contents($this->fsock, $this->decrypt_block_size);
+
+ if (!strlen($raw)) {
+ return '';
+ }
+
+ if ($this->decrypt !== false) {
+ $raw = $this->decrypt->decrypt($raw);
+ }
+ if ($raw === false) {
+ user_error('Unable to decrypt content');
+ return false;
+ }
+
+ if (strlen($raw) < 5) {
+ return false;
+ }
+ extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
+
+ $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
+
+ // quoting <http://tools.ietf.org/html/rfc4253#section-6.1>,
+ // "implementations SHOULD check that the packet length is reasonable"
+ // PuTTY uses 0x9000 as the actual max packet size and so to shall we
+ if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
+ if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt_algorithm) && !($this->bitmap & SSH2::MASK_LOGIN)) {
+ $this->bad_key_size_fix = true;
+ $this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ return false;
+ }
+ user_error('Invalid size');
+ return false;
+ }
+
+ $buffer = '';
+ while ($remaining_length > 0) {
+ $temp = stream_get_contents($this->fsock, $remaining_length);
+ if ($temp === false || feof($this->fsock)) {
+ $this->bitmap = 0;
+ user_error('Error reading from socket');
+ return false;
+ }
+ $buffer.= $temp;
+ $remaining_length-= strlen($temp);
+ }
+
+ $stop = microtime(true);
+ if (strlen($buffer)) {
+ $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
+ }
+
+ $payload = $this->_string_shift($raw, $packet_length - $padding_length - 1);
+ $padding = $this->_string_shift($raw, $padding_length); // should leave $raw empty
+
+ if ($this->hmac_check !== false) {
+ $hmac = stream_get_contents($this->fsock, $this->hmac_size);
+ if ($hmac === false || strlen($hmac) != $this->hmac_size) {
+ $this->bitmap = 0;
+ user_error('Error reading socket');
+ return false;
+ } elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
+ user_error('Invalid HMAC');
+ return false;
+ }
+ }
+
+ //if ($this->decompress) {
+ // $payload = gzinflate(substr($payload, 2));
+ //}
+
+ $this->get_seq_no++;
+
+ if (defined('NET_SSH2_LOGGING')) {
+ $current = microtime(true);
+ $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
+ $message_number = '<- ' . $message_number .
+ ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
+ $this->_append_log($message_number, $payload);
+ $this->last_packet = $current;
+ }
+
+ return $this->_filter($payload, $skip_channel_filter);
+ }
+
+ /**
+ * Filter Binary Packets
+ *
+ * Because some binary packets need to be ignored...
+ *
+ * @see self::_get_binary_packet()
+ * @return string
+ * @access private
+ */
+ function _filter($payload, $skip_channel_filter)
+ {
+ switch (ord($payload[0])) {
+ case NET_SSH2_MSG_DISCONNECT:
+ $this->_string_shift($payload, 1);
+ if (strlen($payload) < 8) {
+ return false;
+ }
+ extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8)));
+ $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . $this->_string_shift($payload, $length);
+ $this->bitmap = 0;
+ return false;
+ case NET_SSH2_MSG_IGNORE:
+ $payload = $this->_get_binary_packet($skip_channel_filter);
+ break;
+ case NET_SSH2_MSG_DEBUG:
+ $this->_string_shift($payload, 2);
+ if (strlen($payload) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($payload, 4)));
+ $this->errors[] = 'SSH_MSG_DEBUG: ' . $this->_string_shift($payload, $length);
+ $payload = $this->_get_binary_packet($skip_channel_filter);
+ break;
+ case NET_SSH2_MSG_UNIMPLEMENTED:
+ return false;
+ case NET_SSH2_MSG_KEXINIT:
+ if ($this->session_id !== false) {
+ $this->send_kex_first = false;
+ if (!$this->_key_exchange($payload)) {
+ $this->bitmap = 0;
+ return false;
+ }
+ $payload = $this->_get_binary_packet($skip_channel_filter);
+ }
+ }
+
+ // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
+ if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
+ $this->_string_shift($payload, 1);
+ if (strlen($payload) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($payload, 4)));
+ $this->banner_message = $this->_string_shift($payload, $length);
+ $payload = $this->_get_binary_packet();
+ }
+
+ // only called when we've already logged in
+ if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
+ switch (ord($payload[0])) {
+ case NET_SSH2_MSG_CHANNEL_DATA:
+ case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
+ case NET_SSH2_MSG_CHANNEL_REQUEST:
+ case NET_SSH2_MSG_CHANNEL_CLOSE:
+ case NET_SSH2_MSG_CHANNEL_EOF:
+ if (!$skip_channel_filter && !empty($this->server_channels)) {
+ $this->binary_packet_buffer = $payload;
+ $this->_get_channel_packet(true);
+ $payload = $this->_get_binary_packet();
+ }
+ break;
+ case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
+ if (strlen($payload) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($payload, 4)));
+ $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
+
+ if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) {
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+
+ $payload = $this->_get_binary_packet($skip_channel_filter);
+ break;
+ case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
+ $this->_string_shift($payload, 1);
+ if (strlen($payload) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($payload, 4)));
+ $data = $this->_string_shift($payload, $length);
+ if (strlen($payload) < 4) {
+ return false;
+ }
+ extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
+ switch ($data) {
+ case 'auth-agent':
+ case 'auth-agent@openssh.com':
+ if (isset($this->agent)) {
+ $new_channel = self::CHANNEL_AGENT_FORWARD;
+
+ if (strlen($payload) < 8) {
+ return false;
+ }
+ extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
+ extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
+
+ $this->packet_size_client_to_server[$new_channel] = $remote_window_size;
+ $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
+ $this->window_size_client_to_server[$new_channel] = $this->window_size;
+
+ $packet_size = 0x4000;
+
+ $packet = pack(
+ 'CN4',
+ NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
+ $server_channel,
+ $new_channel,
+ $packet_size,
+ $packet_size
+ );
+
+ $this->server_channels[$new_channel] = $server_channel;
+ $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+ }
+ break;
+ default:
+ $packet = pack(
+ 'CN3a*Na*',
+ NET_SSH2_MSG_REQUEST_FAILURE,
+ $server_channel,
+ NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
+ 0,
+ '',
+ 0,
+ ''
+ );
+
+ if (!$this->_send_binary_packet($packet)) {
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+ }
+ $payload = $this->_get_binary_packet($skip_channel_filter);
+ break;
+ case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
+ $this->_string_shift($payload, 1);
+ if (strlen($payload) < 8) {
+ return false;
+ }
+ extract(unpack('Nchannel', $this->_string_shift($payload, 4)));
+ extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
+ $this->window_size_client_to_server[$channel]+= $window_size;
+
+ $payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet($skip_channel_filter);
+ }
+ }
+
+ return $payload;
+ }
+
+ /**
+ * Enable Quiet Mode
+ *
+ * Suppress stderr from output
+ *
+ * @access public
+ */
+ function enableQuietMode()
+ {
+ $this->quiet_mode = true;
+ }
+
+ /**
+ * Disable Quiet Mode
+ *
+ * Show stderr in output
+ *
+ * @access public
+ */
+ function disableQuietMode()
+ {
+ $this->quiet_mode = false;
+ }
+
+ /**
+ * Returns whether Quiet Mode is enabled or not
+ *
+ * @see self::enableQuietMode()
+ * @see self::disableQuietMode()
+ * @access public
+ * @return bool
+ */
+ function isQuietModeEnabled()
+ {
+ return $this->quiet_mode;
+ }
+
+ /**
+ * Enable request-pty when using exec()
+ *
+ * @access public
+ */
+ function enablePTY()
+ {
+ $this->request_pty = true;
+ }
+
+ /**
+ * Disable request-pty when using exec()
+ *
+ * @access public
+ */
+ function disablePTY()
+ {
+ if ($this->in_request_pty_exec) {
+ $this->_close_channel(self::CHANNEL_EXEC);
+ $this->in_request_pty_exec = false;
+ }
+ $this->request_pty = false;
+ }
+
+ /**
+ * Returns whether request-pty is enabled or not
+ *
+ * @see self::enablePTY()
+ * @see self::disablePTY()
+ * @access public
+ * @return bool
+ */
+ function isPTYEnabled()
+ {
+ return $this->request_pty;
+ }
+
+ /**
+ * Gets channel data
+ *
+ * Returns the data as a string if it's available and false if not.
+ *
+ * @param $client_channel
+ * @return mixed
+ * @access private
+ */
+ function _get_channel_packet($client_channel, $skip_extended = false)
+ {
+ if (!empty($this->channel_buffers[$client_channel])) {
+ return array_shift($this->channel_buffers[$client_channel]);
+ }
+
+ while (true) {
+ if ($this->binary_packet_buffer !== false) {
+ $response = $this->binary_packet_buffer;
+ $this->binary_packet_buffer = false;
+ } else {
+ $read = array($this->fsock);
+ $write = $except = null;
+
+ if (!$this->curTimeout) {
+ @stream_select($read, $write, $except, null);
+ } else {
+ if ($this->curTimeout < 0) {
+ $this->is_timeout = true;
+ return true;
+ }
+
+ $read = array($this->fsock);
+ $write = $except = null;
+
+ $start = microtime(true);
+ $sec = floor($this->curTimeout);
+ $usec = 1000000 * ($this->curTimeout - $sec);
+ // on windows this returns a "Warning: Invalid CRT parameters detected" error
+ if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
+ $this->is_timeout = true;
+ $this->_close_channel($client_channel);
+ return true;
+ }
+ $elapsed = microtime(true) - $start;
+ $this->curTimeout-= $elapsed;
+ }
+
+ $response = $this->_get_binary_packet(true);
+ if ($response === false) {
+ $this->bitmap = 0;
+ user_error('Connection closed by server');
+ return false;
+ }
+ }
+
+ if ($client_channel == -1 && $response === true) {
+ return true;
+ }
+ if (!strlen($response)) {
+ return false;
+ }
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
+
+ if (strlen($response) < 4) {
+ return false;
+ }
+ if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ } else {
+ extract(unpack('Nchannel', $this->_string_shift($response, 4)));
+ }
+
+ // will not be setup yet on incoming channel open request
+ if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
+ $this->window_size_server_to_client[$channel]-= strlen($response);
+
+ // resize the window, if appropriate
+ if ($this->window_size_server_to_client[$channel] < 0) {
+ $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size);
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+ $this->window_size_server_to_client[$channel]+= $this->window_size;
+ }
+
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
+ /*
+ if ($client_channel == NET_SSH2_CHANNEL_EXEC) {
+ $this->_send_channel_packet($client_channel, chr(0));
+ }
+ */
+ // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
+ if (strlen($response) < 8) {
+ return false;
+ }
+ extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
+ $data = $this->_string_shift($response, $length);
+ $this->stdErrorLog.= $data;
+ if ($skip_extended || $this->quiet_mode) {
+ continue 2;
+ }
+ if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
+ return $data;
+ }
+ if (!isset($this->channel_buffers[$channel])) {
+ $this->channel_buffers[$channel] = array();
+ }
+ $this->channel_buffers[$channel][] = $data;
+
+ continue 2;
+ case NET_SSH2_MSG_CHANNEL_REQUEST:
+ if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) {
+ continue 2;
+ }
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $value = $this->_string_shift($response, $length);
+ switch ($value) {
+ case 'exit-signal':
+ $this->_string_shift($response, 1);
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
+ $this->_string_shift($response, 1);
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ if ($length) {
+ $this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
+ }
+
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
+
+ $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
+
+ continue 3;
+ case 'exit-status':
+ if (strlen($response) < 5) {
+ return false;
+ }
+ extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
+ $this->exit_status = $exit_status;
+
+ // "The client MAY ignore these messages."
+ // -- http://tools.ietf.org/html/rfc4254#section-6.10
+
+ continue 3;
+ default:
+ // "Some systems may not implement signals, in which case they SHOULD ignore this message."
+ // -- http://tools.ietf.org/html/rfc4254#section-6.9
+ continue 3;
+ }
+ }
+
+ switch ($this->channel_status[$channel]) {
+ case NET_SSH2_MSG_CHANNEL_OPEN:
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
+ $this->server_channels[$channel] = $server_channel;
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
+ if ($window_size < 0) {
+ $window_size&= 0x7FFFFFFF;
+ $window_size+= 0x80000000;
+ }
+ $this->window_size_client_to_server[$channel] = $window_size;
+ if (strlen($response) < 4) {
+ return false;
+ }
+ $temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
+ $this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
+ $result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
+ $this->_on_channel_open();
+ return $result;
+ //case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
+ default:
+ user_error('Unable to open channel');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+ break;
+ case NET_SSH2_MSG_CHANNEL_REQUEST:
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_SUCCESS:
+ return true;
+ case NET_SSH2_MSG_CHANNEL_FAILURE:
+ return false;
+ default:
+ user_error('Unable to fulfill channel request');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+ case NET_SSH2_MSG_CHANNEL_CLOSE:
+ return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
+ }
+ }
+
+ // ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA
+
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_DATA:
+ /*
+ if ($channel == self::CHANNEL_EXEC) {
+ // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
+ // this actually seems to make things twice as fast. more to the point, the message right after
+ // SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise.
+ // in OpenSSH it slows things down but only by a couple thousandths of a second.
+ $this->_send_channel_packet($channel, chr(0));
+ }
+ */
+ if (strlen($response) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($response, 4)));
+ $data = $this->_string_shift($response, $length);
+
+ if ($channel == self::CHANNEL_AGENT_FORWARD) {
+ $agent_response = $this->agent->_forward_data($data);
+ if (!is_bool($agent_response)) {
+ $this->_send_channel_packet($channel, $agent_response);
+ }
+ break;
+ }
+
+ if ($client_channel == $channel) {
+ return $data;
+ }
+ if (!isset($this->channel_buffers[$channel])) {
+ $this->channel_buffers[$channel] = array();
+ }
+ $this->channel_buffers[$channel][] = $data;
+ break;
+ case NET_SSH2_MSG_CHANNEL_CLOSE:
+ $this->curTimeout = 0;
+
+ if ($this->bitmap & self::MASK_SHELL) {
+ $this->bitmap&= ~self::MASK_SHELL;
+ }
+ if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) {
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
+ }
+
+ $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
+ if ($client_channel == $channel) {
+ return true;
+ }
+ case NET_SSH2_MSG_CHANNEL_EOF:
+ break;
+ default:
+ user_error('Error reading channel data');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+ }
+ }
+
+ /**
+ * Sends Binary Packets
+ *
+ * See '6. Binary Packet Protocol' of rfc4253 for more info.
+ *
+ * @param string $data
+ * @param string $logged
+ * @see self::_get_binary_packet()
+ * @return bool
+ * @access private
+ */
+ function _send_binary_packet($data, $logged = null)
+ {
+ if (!is_resource($this->fsock) || feof($this->fsock)) {
+ $this->bitmap = 0;
+ user_error('Connection closed prematurely');
+ return false;
+ }
+
+ //if ($this->compress) {
+ // // the -4 removes the checksum:
+ // // http://php.net/function.gzcompress#57710
+ // $data = substr(gzcompress($data), 0, -4);
+ //}
+
+ // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
+ $packet_length = strlen($data) + 9;
+ // round up to the nearest $this->encrypt_block_size
+ $packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size;
+ // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
+ $padding_length = $packet_length - strlen($data) - 5;
+ $padding = Random::string($padding_length);
+
+ // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself
+ $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
+
+ $hmac = $this->hmac_create !== false ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : '';
+ $this->send_seq_no++;
+
+ if ($this->encrypt !== false) {
+ $packet = $this->encrypt->encrypt($packet);
+ }
+
+ $packet.= $hmac;
+
+ $start = microtime(true);
+ $result = strlen($packet) == fputs($this->fsock, $packet);
+ $stop = microtime(true);
+
+ if (defined('NET_SSH2_LOGGING')) {
+ $current = microtime(true);
+ $message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')';
+ $message_number = '-> ' . $message_number .
+ ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
+ $this->_append_log($message_number, isset($logged) ? $logged : $data);
+ $this->last_packet = $current;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Logs data packets
+ *
+ * Makes sure that only the last 1MB worth of packets will be logged
+ *
+ * @param string $data
+ * @access private
+ */
+ function _append_log($message_number, $message)
+ {
+ // remove the byte identifying the message type from all but the first two messages (ie. the identification strings)
+ if (strlen($message_number) > 2) {
+ $this->_string_shift($message);
+ }
+
+ switch (NET_SSH2_LOGGING) {
+ // useful for benchmarks
+ case self::LOG_SIMPLE:
+ $this->message_number_log[] = $message_number;
+ break;
+ // the most useful log for SSH2
+ case self::LOG_COMPLEX:
+ $this->message_number_log[] = $message_number;
+ $this->log_size+= strlen($message);
+ $this->message_log[] = $message;
+ while ($this->log_size > self::LOG_MAX_SIZE) {
+ $this->log_size-= strlen(array_shift($this->message_log));
+ array_shift($this->message_number_log);
+ }
+ break;
+ // dump the output out realtime; packets may be interspersed with non packets,
+ // passwords won't be filtered out and select other packets may not be correctly
+ // identified
+ case self::LOG_REALTIME:
+ switch (PHP_SAPI) {
+ case 'cli':
+ $start = $stop = "\r\n";
+ break;
+ default:
+ $start = '<pre>';
+ $stop = '</pre>';
+ }
+ echo $start . $this->_format_log(array($message), array($message_number)) . $stop;
+ @flush();
+ @ob_flush();
+ break;
+ // basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE
+ // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
+ // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
+ // at the beginning of the file
+ case self::LOG_REALTIME_FILE:
+ if (!isset($this->realtime_log_file)) {
+ // PHP doesn't seem to like using constants in fopen()
+ $filename = self::LOG_REALTIME_FILENAME;
+ $fp = fopen($filename, 'w');
+ $this->realtime_log_file = $fp;
+ }
+ if (!is_resource($this->realtime_log_file)) {
+ break;
+ }
+ $entry = $this->_format_log(array($message), array($message_number));
+ if ($this->realtime_log_wrap) {
+ $temp = "<<< START >>>\r\n";
+ $entry.= $temp;
+ fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
+ }
+ $this->realtime_log_size+= strlen($entry);
+ if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
+ fseek($this->realtime_log_file, 0);
+ $this->realtime_log_size = strlen($entry);
+ $this->realtime_log_wrap = true;
+ }
+ fputs($this->realtime_log_file, $entry);
+ }
+ }
+
+ /**
+ * Sends channel data
+ *
+ * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate
+ *
+ * @param int $client_channel
+ * @param string $data
+ * @return bool
+ * @access private
+ */
+ function _send_channel_packet($client_channel, $data)
+ {
+ while (strlen($data)) {
+ if (!$this->window_size_client_to_server[$client_channel]) {
+ $this->bitmap^= self::MASK_WINDOW_ADJUST;
+ // using an invalid channel will let the buffers be built up for the valid channels
+ $this->_get_channel_packet(-1);
+ $this->bitmap^= self::MASK_WINDOW_ADJUST;
+ }
+
+ /* The maximum amount of data allowed is determined by the maximum
+ packet size for the channel, and the current window size, whichever
+ is smaller.
+ -- http://tools.ietf.org/html/rfc4254#section-5.2 */
+ $max_size = min(
+ $this->packet_size_client_to_server[$client_channel],
+ $this->window_size_client_to_server[$client_channel]
+ );
+
+ $temp = $this->_string_shift($data, $max_size);
+ $packet = pack(
+ 'CN2a*',
+ NET_SSH2_MSG_CHANNEL_DATA,
+ $this->server_channels[$client_channel],
+ strlen($temp),
+ $temp
+ );
+ $this->window_size_client_to_server[$client_channel]-= strlen($temp);
+ if (!$this->_send_binary_packet($packet)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Closes and flushes a channel
+ *
+ * \phpseclib\Net\SSH2 doesn't properly close most channels. For exec() channels are normally closed by the server
+ * and for SFTP channels are presumably closed when the client disconnects. This functions is intended
+ * for SCP more than anything.
+ *
+ * @param int $client_channel
+ * @param bool $want_reply
+ * @return bool
+ * @access private
+ */
+ function _close_channel($client_channel, $want_reply = false)
+ {
+ // see http://tools.ietf.org/html/rfc4254#section-5.3
+
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
+
+ if (!$want_reply) {
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
+ }
+
+ $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
+
+ $this->curTimeout = 0;
+
+ while (!is_bool($this->_get_channel_packet($client_channel))) {
+ }
+
+ if ($want_reply) {
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
+ }
+
+ if ($this->bitmap & self::MASK_SHELL) {
+ $this->bitmap&= ~self::MASK_SHELL;
+ }
+ }
+
+ /**
+ * Disconnect
+ *
+ * @param int $reason
+ * @return bool
+ * @access private
+ */
+ function _disconnect($reason)
+ {
+ if ($this->bitmap & self::MASK_CONNECTED) {
+ $data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
+ $this->_send_binary_packet($data);
+ $this->bitmap = 0;
+ fclose($this->fsock);
+ return false;
+ }
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @return string
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+
+ /**
+ * Define Array
+ *
+ * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
+ * named constants from it, using the value as the name of the constant and the index as the value of the constant.
+ * If any of the constants that would be defined already exists, none of the constants will be defined.
+ *
+ * @param array $array
+ * @access private
+ */
+ function _define_array()
+ {
+ $args = func_get_args();
+ foreach ($args as $arg) {
+ foreach ($arg as $key => $value) {
+ if (!defined($value)) {
+ define($value, $key);
+ } else {
+ break 2;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a log of the packets that have been sent and received.
+ *
+ * Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
+ *
+ * @access public
+ * @return array|false|string
+ */
+ function getLog()
+ {
+ if (!defined('NET_SSH2_LOGGING')) {
+ return false;
+ }
+
+ switch (NET_SSH2_LOGGING) {
+ case self::LOG_SIMPLE:
+ return $this->message_number_log;
+ case self::LOG_COMPLEX:
+ $log = $this->_format_log($this->message_log, $this->message_number_log);
+ return PHP_SAPI == 'cli' ? $log : '<pre>' . $log . '</pre>';
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Formats a log for printing
+ *
+ * @param array $message_log
+ * @param array $message_number_log
+ * @access private
+ * @return string
+ */
+ function _format_log($message_log, $message_number_log)
+ {
+ $output = '';
+ for ($i = 0; $i < count($message_log); $i++) {
+ $output.= $message_number_log[$i] . "\r\n";
+ $current_log = $message_log[$i];
+ $j = 0;
+ do {
+ if (strlen($current_log)) {
+ $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
+ }
+ $fragment = $this->_string_shift($current_log, $this->log_short_width);
+ $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary));
+ // replace non ASCII printable characters with dots
+ // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
+ // also replace < with a . since < messes up the output on web browsers
+ $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
+ $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n";
+ $j++;
+ } while (strlen($current_log));
+ $output.= "\r\n";
+ }
+
+ return $output;
+ }
+
+ /**
+ * Helper function for _format_log
+ *
+ * For use with preg_replace_callback()
+ *
+ * @param array $matches
+ * @access private
+ * @return string
+ */
+ function _format_log_helper($matches)
+ {
+ return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
+ }
+
+ /**
+ * Helper function for agent->_on_channel_open()
+ *
+ * Used when channels are created to inform agent
+ * of said channel opening. Must be called after
+ * channel open confirmation received
+ *
+ * @access private
+ */
+ function _on_channel_open()
+ {
+ if (isset($this->agent)) {
+ $this->agent->_on_channel_open($this);
+ }
+ }
+
+ /**
+ * Returns the first value of the intersection of two arrays or false if
+ * the intersection is empty. The order is defined by the first parameter.
+ *
+ * @param array $array1
+ * @param array $array2
+ * @return mixed False if intersection is empty, else intersected value.
+ * @access private
+ */
+ function _array_intersect_first($array1, $array2)
+ {
+ foreach ($array1 as $value) {
+ if (in_array($value, $array2)) {
+ return $value;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns all errors
+ *
+ * @return string[]
+ * @access public
+ */
+ function getErrors()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * Returns the last error
+ *
+ * @return string
+ * @access public
+ */
+ function getLastError()
+ {
+ $count = count($this->errors);
+
+ if ($count > 0) {
+ return $this->errors[$count - 1];
+ }
+ }
+
+ /**
+ * Return the server identification.
+ *
+ * @return string
+ * @access public
+ */
+ function getServerIdentification()
+ {
+ $this->_connect();
+
+ return $this->server_identifier;
+ }
+
+ /**
+ * Return a list of the key exchange algorithms the server supports.
+ *
+ * @return array
+ * @access public
+ */
+ function getKexAlgorithms()
+ {
+ $this->_connect();
+
+ return $this->kex_algorithms;
+ }
+
+ /**
+ * Return a list of the host key (public key) algorithms the server supports.
+ *
+ * @return array
+ * @access public
+ */
+ function getServerHostKeyAlgorithms()
+ {
+ $this->_connect();
+
+ return $this->server_host_key_algorithms;
+ }
+
+ /**
+ * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getEncryptionAlgorithmsClient2Server()
+ {
+ $this->_connect();
+
+ return $this->encryption_algorithms_client_to_server;
+ }
+
+ /**
+ * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getEncryptionAlgorithmsServer2Client()
+ {
+ $this->_connect();
+
+ return $this->encryption_algorithms_server_to_client;
+ }
+
+ /**
+ * Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getMACAlgorithmsClient2Server()
+ {
+ $this->_connect();
+
+ return $this->mac_algorithms_client_to_server;
+ }
+
+ /**
+ * Return a list of the MAC algorithms the server supports, when sending stuff to the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getMACAlgorithmsServer2Client()
+ {
+ $this->_connect();
+
+ return $this->mac_algorithms_server_to_client;
+ }
+
+ /**
+ * Return a list of the compression algorithms the server supports, when receiving stuff from the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getCompressionAlgorithmsClient2Server()
+ {
+ $this->_connect();
+
+ return $this->compression_algorithms_client_to_server;
+ }
+
+ /**
+ * Return a list of the compression algorithms the server supports, when sending stuff to the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getCompressionAlgorithmsServer2Client()
+ {
+ $this->_connect();
+
+ return $this->compression_algorithms_server_to_client;
+ }
+
+ /**
+ * Return a list of the languages the server supports, when sending stuff to the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getLanguagesServer2Client()
+ {
+ $this->_connect();
+
+ return $this->languages_server_to_client;
+ }
+
+ /**
+ * Return a list of the languages the server supports, when receiving stuff from the client.
+ *
+ * @return array
+ * @access public
+ */
+ function getLanguagesClient2Server()
+ {
+ $this->_connect();
+
+ return $this->languages_client_to_server;
+ }
+
+ /**
+ * Returns the banner message.
+ *
+ * Quoting from the RFC, "in some jurisdictions, sending a warning message before
+ * authentication may be relevant for getting legal protection."
+ *
+ * @return string
+ * @access public
+ */
+ function getBannerMessage()
+ {
+ return $this->banner_message;
+ }
+
+ /**
+ * Returns the server public host key.
+ *
+ * Caching this the first time you connect to a server and checking the result on subsequent connections
+ * is recommended. Returns false if the server signature is not signed correctly with the public host key.
+ *
+ * @return mixed
+ * @access public
+ */
+ function getServerPublicHostKey()
+ {
+ if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
+ if (!$this->_connect()) {
+ return false;
+ }
+ }
+
+ $signature = $this->signature;
+ $server_public_host_key = $this->server_public_host_key;
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ extract(unpack('Nlength', $this->_string_shift($server_public_host_key, 4)));
+ $this->_string_shift($server_public_host_key, $length);
+
+ if ($this->signature_validated) {
+ return $this->bitmap ?
+ $this->signature_format . ' ' . base64_encode($this->server_public_host_key) :
+ false;
+ }
+
+ $this->signature_validated = true;
+
+ switch ($this->signature_format) {
+ case 'ssh-dss':
+ $zero = new BigInteger();
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $p = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $q = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $g = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $y = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
+
+ /* The value for 'dss_signature_blob' is encoded as a string containing
+ r, followed by s (which are 160-bit integers, without lengths or
+ padding, unsigned, and in network byte order). */
+ $temp = unpack('Nlength', $this->_string_shift($signature, 4));
+ if ($temp['length'] != 40) {
+ user_error('Invalid signature');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $r = new BigInteger($this->_string_shift($signature, 20), 256);
+ $s = new BigInteger($this->_string_shift($signature, 20), 256);
+
+ switch (true) {
+ case $r->equals($zero):
+ case $r->compare($q) >= 0:
+ case $s->equals($zero):
+ case $s->compare($q) >= 0:
+ user_error('Invalid signature');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $w = $s->modInverse($q);
+
+ $u1 = $w->multiply(new BigInteger(sha1($this->exchange_hash), 16));
+ list(, $u1) = $u1->divide($q);
+
+ $u2 = $w->multiply($r);
+ list(, $u2) = $u2->divide($q);
+
+ $g = $g->modPow($u1, $p);
+ $y = $y->modPow($u2, $p);
+
+ $v = $g->multiply($y);
+ list(, $v) = $v->divide($p);
+ list(, $v) = $v->divide($q);
+
+ if (!$v->equals($r)) {
+ user_error('Bad server signature');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
+ }
+
+ break;
+ case 'ssh-rsa':
+ case 'rsa-sha2-256':
+ case 'rsa-sha2-512':
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $e = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
+
+ if (strlen($server_public_host_key) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
+ $rawN = $this->_string_shift($server_public_host_key, $temp['length']);
+ $n = new BigInteger($rawN, -256);
+ $nLength = strlen(ltrim($rawN, "\0"));
+
+ /*
+ if (strlen($signature) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($signature, 4));
+ $signature = $this->_string_shift($signature, $temp['length']);
+
+ $rsa = new RSA();
+ switch ($this->signature_format) {
+ case 'rsa-sha2-512':
+ $hash = 'sha512';
+ break;
+ case 'rsa-sha2-256':
+ $hash = 'sha256';
+ break;
+ //case 'ssh-rsa':
+ default:
+ $hash = 'sha1';
+ }
+ $rsa->setHash($hash);
+ $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
+ $rsa->loadKey(array('e' => $e, 'n' => $n), RSA::PUBLIC_FORMAT_RAW);
+
+ if (!$rsa->verify($this->exchange_hash, $signature)) {
+ user_error('Bad server signature');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
+ }
+ */
+
+ if (strlen($signature) < 4) {
+ return false;
+ }
+ $temp = unpack('Nlength', $this->_string_shift($signature, 4));
+ $s = new BigInteger($this->_string_shift($signature, $temp['length']), 256);
+
+ // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
+ // following URL:
+ // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
+
+ // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
+
+ if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) {
+ user_error('Invalid signature');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $s = $s->modPow($e, $n);
+ $s = $s->toBytes();
+
+ switch ($this->signature_format) {
+ case 'rsa-sha2-512':
+ $hash = 'sha512';
+ break;
+ case 'rsa-sha2-256':
+ $hash = 'sha256';
+ break;
+ //case 'ssh-rsa':
+ default:
+ $hash = 'sha1';
+ }
+ $hashObj = new Hash($hash);
+ switch ($this->signature_format) {
+ case 'rsa-sha2-512':
+ $h = pack('N5a*', 0x00305130, 0x0D060960, 0x86480165, 0x03040203, 0x05000440, $hashObj->hash($this->exchange_hash));
+ break;
+ case 'rsa-sha2-256':
+ $h = pack('N5a*', 0x00303130, 0x0D060960, 0x86480165, 0x03040201, 0x05000420, $hashObj->hash($this->exchange_hash));
+ break;
+ //case 'ssh-rsa':
+ default:
+ $hash = 'sha1';
+ $h = pack('N4a*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, $hashObj->hash($this->exchange_hash));
+ }
+ $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
+
+ if ($s != $h) {
+ user_error('Bad server signature');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
+ }
+ break;
+ default:
+ user_error('Unsupported signature format');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
+ }
+
+ return $this->signature_format . ' ' . base64_encode($this->server_public_host_key);
+ }
+
+ /**
+ * Returns the exit status of an SSH command or false.
+ *
+ * @return false|int
+ * @access public
+ */
+ function getExitStatus()
+ {
+ if (is_null($this->exit_status)) {
+ return false;
+ }
+ return $this->exit_status;
+ }
+
+ /**
+ * Returns the number of columns for the terminal window size.
+ *
+ * @return int
+ * @access public
+ */
+ function getWindowColumns()
+ {
+ return $this->windowColumns;
+ }
+
+ /**
+ * Returns the number of rows for the terminal window size.
+ *
+ * @return int
+ * @access public
+ */
+ function getWindowRows()
+ {
+ return $this->windowRows;
+ }
+
+ /**
+ * Sets the number of columns for the terminal window size.
+ *
+ * @param int $value
+ * @access public
+ */
+ function setWindowColumns($value)
+ {
+ $this->windowColumns = $value;
+ }
+
+ /**
+ * Sets the number of rows for the terminal window size.
+ *
+ * @param int $value
+ * @access public
+ */
+ function setWindowRows($value)
+ {
+ $this->windowRows = $value;
+ }
+
+ /**
+ * Sets the number of columns and rows for the terminal window size.
+ *
+ * @param int $columns
+ * @param int $rows
+ * @access public
+ */
+ function setWindowSize($columns = 80, $rows = 24)
+ {
+ $this->windowColumns = $columns;
+ $this->windowRows = $rows;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Pure-PHP ssh-agent client.
+ *
+ * PHP version 5
+ *
+ * Here are some examples of how to use this library:
+ * <code>
+ * <?php
+ * include 'vendor/autoload.php';
+ *
+ * $agent = new \phpseclib\System\SSH\Agent();
+ *
+ * $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
+ * if (!$ssh->login('username', $agent)) {
+ * exit('Login Failed');
+ * }
+ *
+ * echo $ssh->exec('pwd');
+ * echo $ssh->exec('ls -la');
+ * ?>
+ * </code>
+ *
+ * @category System
+ * @package SSH\Agent
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2014 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ * @internal See http://api.libssh.org/rfc/PROTOCOL.agent
+ */
+
+namespace phpseclib\System\SSH;
+
+use phpseclib\Crypt\RSA;
+use phpseclib\System\SSH\Agent\Identity;
+
+/**
+ * Pure-PHP ssh-agent client identity factory
+ *
+ * requestIdentities() method pumps out \phpseclib\System\SSH\Agent\Identity objects
+ *
+ * @package SSH\Agent
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access public
+ */
+class Agent
+{
+ /**#@+
+ * Message numbers
+ *
+ * @access private
+ */
+ // to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
+ const SSH_AGENTC_REQUEST_IDENTITIES = 11;
+ // this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
+ const SSH_AGENT_IDENTITIES_ANSWER = 12;
+ // the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
+ const SSH_AGENTC_SIGN_REQUEST = 13;
+ // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
+ const SSH_AGENT_SIGN_RESPONSE = 14;
+ /**#@-*/
+
+ /**@+
+ * Agent forwarding status
+ *
+ * @access private
+ */
+ // no forwarding requested and not active
+ const FORWARD_NONE = 0;
+ // request agent forwarding when opportune
+ const FORWARD_REQUEST = 1;
+ // forwarding has been request and is active
+ const FORWARD_ACTIVE = 2;
+ /**#@-*/
+
+ /**
+ * Unused
+ */
+ const SSH_AGENT_FAILURE = 5;
+
+ /**
+ * Socket Resource
+ *
+ * @var resource
+ * @access private
+ */
+ var $fsock;
+
+ /**
+ * Agent forwarding status
+ *
+ * @access private
+ */
+ var $forward_status = self::FORWARD_NONE;
+
+ /**
+ * Buffer for accumulating forwarded authentication
+ * agent data arriving on SSH data channel destined
+ * for agent unix socket
+ *
+ * @access private
+ */
+ var $socket_buffer = '';
+
+ /**
+ * Tracking the number of bytes we are expecting
+ * to arrive for the agent socket on the SSH data
+ * channel
+ */
+ var $expected_bytes = 0;
+
+ /**
+ * Default Constructor
+ *
+ * @return \phpseclib\System\SSH\Agent
+ * @access public
+ */
+ function __construct($address = null)
+ {
+ if (!$address) {
+ switch (true) {
+ case isset($_SERVER['SSH_AUTH_SOCK']):
+ $address = $_SERVER['SSH_AUTH_SOCK'];
+ break;
+ case isset($_ENV['SSH_AUTH_SOCK']):
+ $address = $_ENV['SSH_AUTH_SOCK'];
+ break;
+ default:
+ user_error('SSH_AUTH_SOCK not found');
+ return false;
+ }
+ }
+
+ $this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
+ if (!$this->fsock) {
+ user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
+ }
+ }
+
+ /**
+ * Request Identities
+ *
+ * See "2.5.2 Requesting a list of protocol 2 keys"
+ * Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
+ *
+ * @return array
+ * @access public
+ */
+ function requestIdentities()
+ {
+ if (!$this->fsock) {
+ return array();
+ }
+
+ $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
+ if (strlen($packet) != fputs($this->fsock, $packet)) {
+ user_error('Connection closed while requesting identities');
+ return array();
+ }
+
+ $length = current(unpack('N', fread($this->fsock, 4)));
+ $type = ord(fread($this->fsock, 1));
+ if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
+ user_error('Unable to request identities');
+ return array();
+ }
+
+ $identities = array();
+ $keyCount = current(unpack('N', fread($this->fsock, 4)));
+ for ($i = 0; $i < $keyCount; $i++) {
+ $length = current(unpack('N', fread($this->fsock, 4)));
+ $key_blob = fread($this->fsock, $length);
+ $key_str = 'ssh-rsa ' . base64_encode($key_blob);
+ $length = current(unpack('N', fread($this->fsock, 4)));
+ if ($length) {
+ $key_str.= ' ' . fread($this->fsock, $length);
+ }
+ $length = current(unpack('N', substr($key_blob, 0, 4)));
+ $key_type = substr($key_blob, 4, $length);
+ switch ($key_type) {
+ case 'ssh-rsa':
+ $key = new RSA();
+ $key->loadKey($key_str);
+ break;
+ case 'ssh-dss':
+ // not currently supported
+ break;
+ }
+ // resources are passed by reference by default
+ if (isset($key)) {
+ $identity = new Identity($this->fsock);
+ $identity->setPublicKey($key);
+ $identity->setPublicKeyBlob($key_blob);
+ $identities[] = $identity;
+ unset($key);
+ }
+ }
+
+ return $identities;
+ }
+
+ /**
+ * Signal that agent forwarding should
+ * be requested when a channel is opened
+ *
+ * @param Net_SSH2 $ssh
+ * @return bool
+ * @access public
+ */
+ function startSSHForwarding($ssh)
+ {
+ if ($this->forward_status == self::FORWARD_NONE) {
+ $this->forward_status = self::FORWARD_REQUEST;
+ }
+ }
+
+ /**
+ * Request agent forwarding of remote server
+ *
+ * @param Net_SSH2 $ssh
+ * @return bool
+ * @access private
+ */
+ function _request_forwarding($ssh)
+ {
+ $request_channel = $ssh->_get_open_channel();
+ if ($request_channel === false) {
+ return false;
+ }
+
+ $packet = pack(
+ 'CNNa*C',
+ NET_SSH2_MSG_CHANNEL_REQUEST,
+ $ssh->server_channels[$request_channel],
+ strlen('auth-agent-req@openssh.com'),
+ 'auth-agent-req@openssh.com',
+ 1
+ );
+
+ $ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
+
+ if (!$ssh->_send_binary_packet($packet)) {
+ return false;
+ }
+
+ $response = $ssh->_get_channel_packet($request_channel);
+ if ($response === false) {
+ return false;
+ }
+
+ $ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
+ $this->forward_status = self::FORWARD_ACTIVE;
+
+ return true;
+ }
+
+ /**
+ * On successful channel open
+ *
+ * This method is called upon successful channel
+ * open to give the SSH Agent an opportunity
+ * to take further action. i.e. request agent forwarding
+ *
+ * @param Net_SSH2 $ssh
+ * @access private
+ */
+ function _on_channel_open($ssh)
+ {
+ if ($this->forward_status == self::FORWARD_REQUEST) {
+ $this->_request_forwarding($ssh);
+ }
+ }
+
+ /**
+ * Forward data to SSH Agent and return data reply
+ *
+ * @param string $data
+ * @return data from SSH Agent
+ * @access private
+ */
+ function _forward_data($data)
+ {
+ if ($this->expected_bytes > 0) {
+ $this->socket_buffer.= $data;
+ $this->expected_bytes -= strlen($data);
+ } else {
+ $agent_data_bytes = current(unpack('N', $data));
+ $current_data_bytes = strlen($data);
+ $this->socket_buffer = $data;
+ if ($current_data_bytes != $agent_data_bytes + 4) {
+ $this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
+ return false;
+ }
+ }
+
+ if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
+ user_error('Connection closed attempting to forward data to SSH agent');
+ }
+
+ $this->socket_buffer = '';
+ $this->expected_bytes = 0;
+
+ $agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
+
+ $agent_reply_data = fread($this->fsock, $agent_reply_bytes);
+ $agent_reply_data = current(unpack('a*', $agent_reply_data));
+
+ return pack('Na*', $agent_reply_bytes, $agent_reply_data);
+ }
+}
--- /dev/null
+<?php
+/**
+ * Pure-PHP ssh-agent client.
+ *
+ * PHP version 5
+ *
+ * @category System
+ * @package SSH\Agent
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @copyright 2009 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ * @internal See http://api.libssh.org/rfc/PROTOCOL.agent
+ */
+
+namespace phpseclib\System\SSH\Agent;
+
+use phpseclib\System\SSH\Agent;
+
+/**
+ * Pure-PHP ssh-agent client identity object
+ *
+ * Instantiation should only be performed by \phpseclib\System\SSH\Agent class.
+ * This could be thought of as implementing an interface that phpseclib\Crypt\RSA
+ * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
+ * The methods in this interface would be getPublicKey and sign since those are the
+ * methods phpseclib looks for to perform public key authentication.
+ *
+ * @package SSH\Agent
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @access internal
+ */
+class Identity
+{
+ /**@+
+ * Signature Flags
+ *
+ * See https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-5.3
+ *
+ * @access private
+ */
+ const SSH_AGENT_RSA2_256 = 2;
+ const SSH_AGENT_RSA2_512 = 4;
+ /**#@-*/
+
+ /**
+ * Key Object
+ *
+ * @var \phpseclib\Crypt\RSA
+ * @access private
+ * @see self::getPublicKey()
+ */
+ var $key;
+
+ /**
+ * Key Blob
+ *
+ * @var string
+ * @access private
+ * @see self::sign()
+ */
+ var $key_blob;
+
+ /**
+ * Socket Resource
+ *
+ * @var resource
+ * @access private
+ * @see self::sign()
+ */
+ var $fsock;
+
+ /**
+ * Signature flags
+ *
+ * @var int
+ * @access private
+ * @see self::sign()
+ * @see self::setHash()
+ */
+ var $flags = 0;
+
+ /**
+ * Default Constructor.
+ *
+ * @param resource $fsock
+ * @return \phpseclib\System\SSH\Agent\Identity
+ * @access private
+ */
+ function __construct($fsock)
+ {
+ $this->fsock = $fsock;
+ }
+
+ /**
+ * Set Public Key
+ *
+ * Called by \phpseclib\System\SSH\Agent::requestIdentities()
+ *
+ * @param \phpseclib\Crypt\RSA $key
+ * @access private
+ */
+ function setPublicKey($key)
+ {
+ $this->key = $key;
+ $this->key->setPublicKey();
+ }
+
+ /**
+ * Set Public Key
+ *
+ * Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
+ * but this saves a small amount of computation.
+ *
+ * @param string $key_blob
+ * @access private
+ */
+ function setPublicKeyBlob($key_blob)
+ {
+ $this->key_blob = $key_blob;
+ }
+
+ /**
+ * Get Public Key
+ *
+ * Wrapper for $this->key->getPublicKey()
+ *
+ * @param int $format optional
+ * @return mixed
+ * @access public
+ */
+ function getPublicKey($format = null)
+ {
+ return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
+ }
+
+ /**
+ * Set Signature Mode
+ *
+ * Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
+ * ssh-agent's only supported mode is \phpseclib\Crypt\RSA::SIGNATURE_PKCS1
+ *
+ * @param int $mode
+ * @access public
+ */
+ function setSignatureMode($mode)
+ {
+ }
+
+ /**
+ * Set Hash
+ *
+ * ssh-agent doesn't support using hashes for RSA other than SHA1
+ *
+ * @param string $hash
+ * @access public
+ */
+ function setHash($hash)
+ {
+ $this->flags = 0;
+ switch ($hash) {
+ case 'sha1':
+ break;
+ case 'sha256':
+ $this->flags = self::SSH_AGENT_RSA2_256;
+ break;
+ case 'sha512':
+ $this->flags = self::SSH_AGENT_RSA2_512;
+ break;
+ default:
+ user_error('The only supported hashes for RSA are sha1, sha256 and sha512');
+ }
+ }
+
+ /**
+ * Create a signature
+ *
+ * See "2.6.2 Protocol 2 private key signature request"
+ *
+ * @param string $message
+ * @return string
+ * @access public
+ */
+ function sign($message)
+ {
+ // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
+ $packet = pack('CNa*Na*N', Agent::SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, $this->flags);
+ $packet = pack('Na*', strlen($packet), $packet);
+ if (strlen($packet) != fputs($this->fsock, $packet)) {
+ user_error('Connection closed during signing');
+ }
+
+ $length = current(unpack('N', fread($this->fsock, 4)));
+ $type = ord(fread($this->fsock, 1));
+ if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
+ user_error('Unable to retrieve signature');
+ }
+
+ $signature_blob = fread($this->fsock, $length - 1);
+ $length = current(unpack('N', $this->_string_shift($signature_blob, 4)));
+ if ($length != strlen($signature_blob)) {
+ user_error('Malformed signature blob');
+ }
+ $length = current(unpack('N', $this->_string_shift($signature_blob, 4)));
+ if ($length > strlen($signature_blob) + 4) {
+ user_error('Malformed signature blob');
+ }
+ $type = $this->_string_shift($signature_blob, $length);
+ $this->_string_shift($signature_blob, 4);
+
+ return $signature_blob;
+ }
+
+ /**
+ * String Shift
+ *
+ * Inspired by array_shift
+ *
+ * @param string $string
+ * @param int $index
+ * @return string
+ * @access private
+ */
+ function _string_shift(&$string, $index = 1)
+ {
+ $substr = substr($string, 0, $index);
+ $string = substr($string, $index);
+ return $substr;
+ }
+}
--- /dev/null
+<?php
+/**
+ * Bootstrapping File for phpseclib
+ *
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ */
+
+if (extension_loaded('mbstring')) {
+ // 2 - MB_OVERLOAD_STRING
+ if (ini_get('mbstring.func_overload') & 2) {
+ throw new \UnexpectedValueException(
+ 'Overloading of string functions using mbstring.func_overload ' .
+ 'is not supported by phpseclib.'
+ );
+ }
+}
--- /dev/null
+# minimalist openssl.cnf file for use with phpseclib
+
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+[ v3_ca ]
+++ /dev/null
-# ramsey/uuid Changelog
-
-## 3.8.0
-
-_Released: 2018-07-19_
-
- * Add support for determining MAC address on FreeBSD systems ([#212](https://github.com/ramsey/uuid/pull/212))
- * Add a polyfill for PHP ctype functions to support systems where the ctype functions are not part of the PHP build ([#223](https://github.com/ramsey/uuid/pull/223))
- * Improve validation to disallow UUIDs with a trailing newline character ([#225](https://github.com/ramsey/uuid/pull/225))
- * Add annotations for thrown exceptions for improved IDE hinting ([#232](https://github.com/ramsey/uuid/pull/232))
- * Improve documentation, testing, and project metadata (i.e. `.gitattributes`, etc.)
-
-## 3.7.3
-
-_Released: 2018-01-19_
-
- * In rare cases, when using `glob()` to find `/sys/class/net/*/address` files on Linux, `glob()` encountered errors, returning `false` instead of an empty array, causing `array_map()` to emit warnings since its second parameter was not an array; this release gracefully handles cases where `glob()` returns `false` [#203](https://github.com/ramsey/uuid/issues/203)
- * Fixed an off-by-one error in `DefaultTimeGenerator` and switching to `random_int()` from `mt_rand()` for better random numbers [#206](https://github.com/ramsey/uuid/pull/206)
-
-## 3.7.2
-
-_Released: 2018-01-13_
-
- * On Linux, first check sysfs to determine node identifier; this provides a reliable way to identify the node on Docker images, etc. [#185](https://github.com/ramsey/uuid/pull/185)
-
-## 3.7.1
-
-_Released: 2017-09-22_
-
- * Use `random_bytes()` when generating random nodes
- * Set the multicast bit for random nodes, according to RFC 4122, §4.5, [#170](https://github.com/ramsey/uuid/pull/170), [#171](https://github.com/ramsey/uuid/pull/171), [#182](https://github.com/ramsey/uuid/pull/182)
-
-## 3.7.0
-
-_Released: 2017-08-04_
-
- * Add UUID version constants [#173](https://github.com/ramsey/uuid/issues/173), [#177](https://github.com/ramsey/uuid/pull/177)
- * `Uuid::UUID_TYPE_TIME`
- * `Uuid::UUID_TYPE_IDENTIFIER`
- * `Uuid::UUID_TYPE_HASH_MD5`
- * `Uuid::UUID_TYPE_RANDOM`
- * `Uuid::UUID_TYPE_HASH_SHA1`
-
-## 3.6.1
-
-_Released: 2017-03-26_
-
- * Optimize UUID string decoding [#164](https://github.com/ramsey/uuid/pull/164)
-
-## 3.6.0
-
-_Released: 2017-03-18_
-
- * Add `InvalidUuidStringException`, thrown when attempting to decode an invalid string UUID; this does not introduce any BC issues, since the new exception inherits from the previously used `InvalidArgumentException` [#162](https://github.com/ramsey/uuid/pull/162)
- * Improve memory usage when generating large quantities of UUIDs (use `str_pad()` and `dechex()` instead of `sprintf()`) [#160](https://github.com/ramsey/uuid/pull/160)
- * Minor test and documentation updates
-
-## 3.5.2
-
-_Released: 2016-11-22_
-
- * Improved test coverage.
-
-## 3.5.1
-
-_Released: 2016-10-02_
-
- * Fixed issue where same UUIDs were not treated as equal with mixed case ([#131](https://github.com/ramsey/uuid/issues/131), [#137](https://github.com/ramsey/uuid/pull/137)).
- * Test cleanup.
-
-## 3.5.0
-
-_Released: 2016-08-02_
-
- * Add `OrderedTimeCodec` to store UUID in an optimized way for InnoDB ([#117](https://github.com/ramsey/uuid/issues/117), [#118](https://github.com/ramsey/uuid/pull/118)).
- * Fixed `RandomNodeProvider` to prevent invalid node generation ([#129](https://github.com/ramsey/uuid/pull/129)).
- * Cache failed attempt to retrieve system node to avoid multiple system calls ([#107](https://github.com/ramsey/uuid/issues/107), [#121](https://github.com/ramsey/uuid/pull/121)).
- * Various test improvements.
-
-## 3.4.1
-
-_Released: 2016-04-23_
-
- * Fixed test that violated a PHP CodeSniffer rule, breaking the build.
-
-## 3.4.0
-
-_Released: 2016-04-23_
-
- * Add `TimestampFirstCombCodec` and `TimestampLastCombCodec` codecs.
- * Improve logic of `CombGenerator` for COMB sequential UUIDs.
- * Significantly improved test coverage.
-
-## 3.3.0
-
-_Released: 2016-03-22_
-
- * Drop the use of OpenSSL as a fallback and use [paragonie/random_compat][] to support RandomBytesGenerator in versions of PHP earlier than 7.0. This addresses and fixes the [collision issue][].
- * Improved test coverage.
- * Update code to conduct to version 1.4 of the Contributor Covenant.
-
-## 3.2.0
-
-_Released: 2016-02-17_
-
- * Add random generator option for use for the PECL libsodium extension.
- * Updates to test infrastructure.
-
-## 3.1.0
-
-_Released: 2015-12-17_
-
- * Uuid objects now may be properly serialized/unserialized.
- * Update build environments for testing on Travis CI.
-
-## 3.0.1
-
-_Released: 2015-10-21_
-
- * Add project [Contributor Code of Conduct](https://github.com/ramsey/uuid/blob/master/CONDUCT.md)
- * Modify Travis CI builds to run tests on multiple CPU architectures
- * Clean up code, tests, and documentation
-
-## 3.0.0
-
-_Released: 2015-09-28_
-
-The 3.0.0 release represents a significant step for the ramsey/uuid library. While the simple and familiar API used in previous versions remains intact, this release provides greater flexibility to integrators, including the ability to inject your own number generators, UUID codecs, node and time providers, and more.
-
- * BREAK: The root namespace for this package has changed from "Rhumsaa" to "Ramsey." In most cases, simply making this change in your applications is the only upgrade path you will need. Everything else should work as expected.
- * BREAK: The UUID [Doctrine field type](http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html) has been moved to [ramsey/uuid-doctrine](https://github.com/ramsey/uuid-doctrine).
- * BREAK: The `uuid` console application has been moved to [ramsey/uuid-console](https://github.com/ramsey/uuid-console).
- * BREAK: The `Uuid::VERSION` package version constant has been removed.
- * See also the release notes for [3.0.0-alpha1][300-alpha1], [3.0.0-alpha2][300-alpha2], [3.0.0-alpha3][300-alpha3], and [3.0.0-beta1][300-beta1].
-
-[300-alpha1]: https://github.com/ramsey/uuid/blob/master/CHANGELOG.md#300-alpha1
-[300-alpha2]: https://github.com/ramsey/uuid/blob/master/CHANGELOG.md#300-alpha2
-[300-alpha3]: https://github.com/ramsey/uuid/blob/master/CHANGELOG.md#300-alpha3
-[300-beta1]: https://github.com/ramsey/uuid/blob/master/CHANGELOG.md#300-beta1
-
-## 3.0.0-beta1
-
-_Released: 2015-08-31_
-
- * Improve GUID support to ensure that:
- * On little endian (LE) architectures, the byte order of the first three fields is LE.
- * On big endian (BE) architectures, it is the same as a GUID.
- * String representation is always the same.
- * Fix exception message for `DegradedNumberConverter::fromHex()`.
- * Add Scrutinizer configuration to run code-quality builds through Scrutinizer.
- * Auto-fix Scrutinizer issues.
- * Fix support URLs in composer.json to point to the correct GitHub repository.
-
-## 3.0.0-alpha3
-
-_Released: 2015-07-28_
-
- * Time generator improvements:
- * Enabled use of custom TimeGenerator implementations.
- * BREAK: Removed now unnecessary `timeConverter` and `timeProvider` properties, setters, and getters in both `FeatureSet` and `UuidFactory` as those are now exclusively used by the default `TimeGenerator`.
- * Added a `setTimeGenerator` method on `UuidFactory` to override the default time generator.
- * Add option to enable `PeclUuidTimeGenerator` via `FeatureSet`.
-
-## 3.0.0-alpha2
-
-_Released: 2015-07-28_
-
- * BREAK: Removed `PeclUuidFactory` in favor of using pecl-uuid with generators.
- * NEW: Refactored time-based (version 1) UUIDs into a `TimeGeneratorInterface` to allow for other sources to generate version 1 UUIDs in this library.
- * NEW: Added `PeclUuidTimeGenerator` and `PeclUuidRandomGenerator` for creating version 1 or version 4 UUIDs using the pecl-uuid extension.
- * NEW: Add `RandomBytesGenerator` for use with PHP 7. ramsey/uuid will default to use this generator when running on PHP 7.
- * `RandomLibAdapter` now defaults to a medium-strength generator with [ircmaxell/random-lib](https://github.com/ircmaxell/RandomLib). This is configurable, so other generator strengths may be used.
- * Migrated to the Travis CI container-based infrastructure for builds.
- * Documentation updates and corrections.
-
-## 3.0.0-alpha1
-
-_Released: 2015-07-16_
-
- * BREAK: The root namespace for this package has changed from "Rhumsaa" to "Ramsey." In most cases, simply making this change in your applications is the only upgrade path you will need. Everything else should work as expected.
- * BREAK: The UUID [Doctrine field type](http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html) has been moved to [ramsey/uuid-doctrine](https://github.com/ramsey/uuid-doctrine).
- * BREAK: The `uuid` console application has been moved to [ramsey/uuid-console](https://github.com/ramsey/uuid-console).
- * BREAK: The `Uuid::VERSION` package version constant has been removed.
- * NEW: The `Uuid` class is no longer marked as `final`. Everything is now based around interfaces and factories, allowing you to use this package as a base to implement other kinds of UUIDs with different dependencies.
- * NEW: Through setting dependencies on `UuidFactory` and/or extending `FeatureSet`, you may override any package defaults, injecting your own dependencies.
- * NEW: For random number generation, in addition to `OpenSslGenerator` (used if `openssl_random_pseudo_bytes()` is present) and the fallback `MtRandGenerator`, you may use the bundled `CombGenerator` for sequential UUIDs or the `RandomLibAdapter` if using [ircmaxell/random-lib](https://github.com/ircmaxell/RandomLib).
- * NEW: In addition to the default UUID generation, this library also supports GUID generation by configuring a `FeatureSet` to use GUIDs.
- * NEW: While the interface to create UUIDs hasn't changed, if using this package on a 32-bit system, you will now receive an object of type `DegradedUuid` (which extends `Uuid`, which implements `UuidInterface`).
- * NEW: All UUIDs are now [JsonSerializable](http://php.net/JsonSerializable).
-
-## 2.9.0
-
-_Released: 2016-03-22_
-
- * Drop support for OpenSSL in favor of [paragonie/random_compat][]. This addresses and fixes the [collision issue][].
-
-## 2.8.4
-
-_Released: 2015-12-17_
-
- * Add support for symfony/console v3.
- * Update build matrix to run Travis CI tests on PHP 7 & with lowest package versions.
-
-## 2.8.3
-
-_Released: 2015-08-31_
-
- * Fix exception message in `Uuid::calculateUuidTime()`.
- * Update composer.json to reflect new repository and package name.
-
-## 2.8.2
-
-_Released: 2015-07-23_
-
- * Ensure the release tag makes it into the rhumsaa/uuid package.
- * Minor documentation changes.
-
-## 2.8.1
-
-_Released: 2015-06-16_
-
- * Use `passthru()` and output buffering in `getIfconfig()`.
- * Cache the system node in a static variable so that we process it only once per runtime.
- * Set ramsey/uuid as a replacement for rhumsaa/uuid in composer.json.
- * Documentation updates and corrections.
-
-## 2.8.0
-
-_Released: 2014-11-09_
-
- * Added static `fromInteger()` method to create UUIDs from string integer or `\Moontoast\Math\BigNumber`.
- * Friendlier Doctrine conversion to Uuid or string.
- * Documentation fixes.
-
-## 2.7.4
-
-_Released: 2014-10-29_
-
- * Changed loop in `generateBytes()` from `foreach` to `for`; see #33
- * Use `toString()` in README examples to avoid confusion
- * Exclude build/development tools from releases using .gitattributes
- * Set timezone properly for tests
-
-## 2.7.3
-
-_Released: 2014-08-27_
-
- * Fixed upper range for `mt_rand` used in version 4 UUIDs
-
-## 2.7.2
-
-_Released: 2014-07-28_
-
- * Upgraded to PSR-4 autoloading
- * Testing upgrades:
- * Testing against PHP 5.6
- * Testing with PHPUnit 4
- * Using Coveralls.io to generate code coverage reports
- * Documentation fixes
-
-## 2.7.1
-
-_Released: 2014-02-19_
-
- * Moved moontoast/math and symfony/console to require-dev; fixes #20
- * Now supporting symfony/console for 2.3 (LTS version); fixes #21
- * Updated tests to run even when dev packages are not installed (skips tests if requirements are not met)
-
-## 2.7.0
-
-_Released: 2014-01-31_
-
- * Moved UUID validation regex pattern into constant for external use (`Uuid::VALID_PATTERN`)
-
-## 2.6.1
-
-_Released: 2014-01-27_
-
- * Fixed bug where `uuid` console application could not find the Composer autoloader when installed in another project
-
-## 2.6.0
-
-_Released: 2014-01-17_
-
- * Introduced `uuid` console application for generating and decoding UUIDs from CLI (run `./bin/uuid` for details)
- * Added `Uuid::getInteger()` to retrieve a Moontoast\Math\BigNumber representation of the 128-bit integer representing the UUID
- * Added `Uuid::getHex()` to retrieve the hexadecimal representation of the UUID
- * Now using netstat on Linux to capture the node for a version 1 UUID
- * Now requiring Moontoast\Math as part of the regular package requirements, not just the dev requirements
-
-## 2.5.0
-
-_Released: 2013-10-30_
-
- * Using `openssl_random_pseudo_bytes()`, if available, to generate random bytes, by merging in PR #15 from @dfreudenberger
- * Fixed test for Rhumsaa\Uuid\Doctrine\UuidType, by merging in PR #17 from @dfreudenberger
- * Documentation fixes
-
-## 2.4.0
-
-_Released: 2013-07-29_
-
- * `Uuid::getVersion()` now returns null if the UUID isn't an RFC 4122 variant
- * `Uuid::fromString()` now supports a 128-bit integer formatted as a hexadecimal string (UUID without dashes)
- * Tests have been greatly enhanced, borrowing from the Python UUID library
-
-## 2.3.0
-
-_Released: 2013-07-16_
-
- * Added `Uuid::fromBytes()` by merging in PR #14 from @asm89
-
-## 2.2.0
-
-_Released: 2013-07-04_
-
- * Added `Doctrine\UuidType::requiresSQLCommentHint()` method by merging in PR #13 from @zerrvox
- * Removed `"minimum-stability": "dev"` from composer.json
-
-## 2.1.2
-
-_Released: 2013-07-03_
-
- * @ericthelin found cases where the system node was coming back with uppercase hexadecimal digits; this ensures that case in the node is converted to lowercase
-
-## 2.1.1
-
-_Released: 2013-04-29_
-
- * Fixed NIL bug in `Uuid::isValid()` method, reported by @ocubom in PR #11
-
-## 2.1.0
-
-_Released: 2013-04-15_
-
- * Added static `Uuid::isValid()` method for checking whether a string is a valid UUID
-
-## 2.0.0
-
-_Released: 2013-02-11_
-
- * Break: `Uuid` class is now marked as "final"
- * Break: `Uuid::getLeastSignificantBits()` no longer returns an integer on 64-bit platforms; it requires `moontoast/math`
- * Break: `Uuid::getMostSignificantBits()` no longer returns an integer on 64-bit platforms; it requires `moontoast/math`
- * Break: Moved `UnsupportedOperationException` to the `Exception` subnamespace
- * Added support for 32-bit platforms
- * Added generated API documentation to the repository
-
-## 1.1.2
-
-_Released: 2012-11-29_
-
- * Relaxed Doctrine type conversion rules
-
-## 1.1.1
-
-_Released: 2012-08-27_
-
- * Removed `final` keyword from `Uuid` class
-
-## 1.1.0
-
-_Released: 2012-08-06_
-
- * Added `Doctrine\UuidType` as a field mapping type for the Doctrine Database Abstraction Layer (DBAL)
- * Improved tests and code coverage
-
-## 1.0.0
-
-_Released: 2012-07-19_
-
- * Initial release
-
-
-[paragonie/random_compat]: https://github.com/paragonie/random_compat
-[collision issue]: https://github.com/ramsey/uuid/issues/80
+++ /dev/null
-# Contributor Code of Conduct
-
-## Our Pledge
-
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, gender identity and expression, level of experience,
-nationality, personal appearance, race, religion, or sexual identity and
-orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery and unwelcome sexual attention or
-advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
-
-## Scope
-
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project maintainer at <ben@benramsey.com>. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an incident.
-Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
-
-## Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
-available at [http://contributor-covenant.org/version/1/4][version]
-
-[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
+++ /dev/null
-# Contributing
-
-Contributions are welcome. We accept pull requests on [GitHub](https://github.com/ramsey/uuid).
-
-This project adheres to a [Contributor Code of Conduct](https://github.com/ramsey/uuid/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.
-
-## Team members
-
-* [Ben Ramsey](https://github.com/ramsey) - original author and maintainer
-* [Marijn Huizendveld](https://github.com/marijn) - contributor, author of UUID type definition for Doctrine DBAL
-* [Thibaud Fabre](https://github.com/aztech-dev) - contributor, lead developer for version 3.0.0 re-architecture
-
-## Communication Channels
-
-You can find help and discussion in the following places:
-
-* GitHub Issues: <https://github.com/ramsey/uuid/issues>
-* Wiki: <https://github.com/ramsey/uuid/wiki>
-
-## Reporting Bugs
-
-Bugs are tracked in our project's [issue tracker](https://github.com/ramsey/uuid/issues).
-
-When submitting a bug report, please include enough information for us to reproduce the bug. A good bug report includes the following sections:
-
-* Expected outcome
-* Actual outcome
-* Steps to reproduce, including sample code
-* Any other information that will help us debug and reproduce the issue, including stack traces, system/environment information, and screenshots
-
-**Please do not include passwords or any personally identifiable information in your bug report and sample code.**
-
-## Fixing Bugs
-
-We welcome pull requests to fix bugs!
-
-If you see a bug report that you'd like to fix, please feel free to do so. Following the directions and guidelines described in the "Adding New Features" section below, you may create bugfix branches and send us pull requests.
-
-## Adding New Features
-
-If you have an idea for a new feature, it's a good idea to check out our [issues](https://github.com/ramsey/uuid/issues) or active [pull requests](https://github.com/ramsey/uuid/pulls) first to see if the feature is already being worked on. If not, feel free to submit an issue first, asking whether the feature is beneficial to the project. This will save you from doing a lot of development work only to have your feature rejected. We don't enjoy rejecting your hard work, but some features just don't fit with the goals of the project.
-
-When you do begin working on your feature, here are some guidelines to consider:
-
-* Your pull request description should clearly detail the changes you have made. We will use this description to add to our CHANGELOG. If there is no description or it does not adequately describe your feature, we will ask you to update the description.
-* We following the **[PSR-2 coding standard](http://www.php-fig.org/psr/psr-2/)**. Please ensure your code does, too.
-* Please **write tests** for any new features you add.
-* Please **ensure that tests pass** before submitting your pull request. We have Travis CI automatically running tests for pull requests. However, running the tests locally will help save time.
-* **Use topic/feature branches.** Please do not ask us to pull from your master branch.
-* **Submit one feature per pull request.** If you have multiple features you wish to submit, please break them up into separate pull requests.
-* **Send coherent history**. Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
-
-## Running Tests
-
-The following tests must pass before we will accept a pull request. If any of these do not pass, it will result in a complete build failure. Before you can run these, be sure to `composer install`.
-
-```
-composer test
-```
-
-### Locally Test With Emulated MIPS Architecture
-
-The following commands use [Vagrant](https://www.vagrantup.com/) to start an Ubuntu VM, install necessary dependencies, and then run the `tools/run-tests.sh` script that will download a Docker image emulating the MIPS architecture. This is especially helpful for testing UUID generation in a big-endian environment.
-
-```
-vagrant init ubuntu/trusty64
-vagrant up
-vagrant ssh
-sudo apt-get install docker.io qemu-user-static php5-cli php5-curl
-cd /vagrant
-curl -sS https://getcomposer.org/installer | php
-php composer.phar install --no-interaction --prefer-dist
-mkdir -p build/logs
-ARCH=mips PHP_VERSION=5.6.14 TRAVIS_BUILD_DIR=/vagrant ./tools/run-tests.sh
-```
+++ /dev/null
-Copyright (c) 2012-2018 Ben Ramsey <ben@benramsey.com>
-
-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.
+++ /dev/null
-# ramsey/uuid
-
-_NOTICE: Formerly known as `rhumsaa/uuid`, The package and namespace names have changed to `ramsey/uuid` and `Ramsey\Uuid`, respectively._
-
-[![Source Code][badge-source]][source]
-[![Latest Version][badge-release]][release]
-[![Software License][badge-license]][license]
-[![Build Status][badge-build]][build]
-[![Coverage Status][badge-coverage]][coverage]
-[![Total Downloads][badge-downloads]][downloads]
-
-ramsey/uuid is a PHP 5.4+ library for generating and working with [RFC 4122][rfc4122] version 1, 3, 4, and 5 universally unique identifiers (UUID).
-
-This project adheres to a [Contributor Code of Conduct][conduct]. By participating in this project and its community, you are expected to uphold this code.
-
-
-## About
-
-From [Wikipedia](http://en.wikipedia.org/wiki/Universally_unique_identifier):
-
-> The intent of UUIDs is to enable distributed systems to uniquely identify information without significant central coordination. In this context the word unique should be taken to mean "practically unique" rather than "guaranteed unique". Since the identifiers have a finite size, it is possible for two differing items to share the same identifier. The identifier size and generation process need to be selected so as to make this sufficiently improbable in practice. Anyone can create a UUID and use it to identify something with reasonable confidence that the same identifier will never be unintentionally created by anyone to identify something else. Information labeled with UUIDs can therefore be later combined into a single database without needing to resolve identifier (ID) conflicts.
-
-Much inspiration for this library came from the [Java][javauuid] and [Python][pyuuid] UUID libraries.
-
-
-## Installation
-
-The preferred method of installation is via [Packagist][] and [Composer][]. Run the following command to install the package and add it as a requirement to your project's `composer.json`:
-
-```bash
-composer require ramsey/uuid
-```
-
-
-## Upgrading from 2.x to 3.x
-
-While we have made significant internal changes to the library, we have made every effort to ensure a seamless upgrade path from the 2.x series of this library to 3.x.
-
-One major breaking change is the transition from the `Rhumsaa` root namespace to `Ramsey`. In most cases, all you will need is to change the namespace to `Ramsey` in your code, and everything will "just work."
-
-Here are full details on the breaking changes to the public API of this library:
-
-1. All namespace references of `Rhumsaa` have changed to `Ramsey`. Simply change the namespace to `Ramsey` in your code and everything should work.
-2. The console application has moved to [ramsey/uuid-console](https://packagist.org/packages/ramsey/uuid-console). If using the console functionality, use Composer to require `ramsey/uuid-console`.
-3. The Doctrine field type mapping has moved to [ramsey/uuid-doctrine](https://packagist.org/packages/ramsey/uuid-doctrine). If using the Doctrine functionality, use Composer to require `ramsey/uuid-doctrine`.
-
-
-## What to do if you see a "rhumsaa/uuid is abandoned" message
-
-When installing your project's dependencies using Composer, you might see the following message:
-
-```
-Package rhumsaa/uuid is abandoned, you should avoid using it. Use ramsey/uuid instead.
-```
-
-Don't panic. Simply execute the following commands with Composer:
-
-``` bash
-composer remove rhumsaa/uuid
-composer require ramsey/uuid=^2.9
-```
-
-After doing so, you will have the latest ramsey/uuid package in the 2.x series, and there will be no need to modify any code; the namespace in the 2.x series is still `Rhumsaa`.
-
-
-## Requirements
-
-Some methods in this library have requirements due to integer size restrictions on 32-bit and 64-bit builds of PHP. A 64-bit build of PHP and the [Moontoast\Math][] library are recommended. However, this library is designed to work on 32-bit builds of PHP without Moontoast\Math, with some degraded functionality. Please check the API documentation for more information.
-
-If a particular requirement is not present, then an `UnsatisfiedDependencyException` is thrown, allowing one to catch a bad call in an environment where the call is not supported and gracefully degrade.
-
-
-## API documentation
-
-The [latest class API documentation][apidocs] is available online.
-
-This project uses [ApiGen](http://apigen.org/) to generate this documentation. To generate the documentation on your own, install dev dependencies and run the following command from the root of the project:
-
-```
-composer build-docs
-```
-
-This will generate documentation in the `build/apidocs/` folder.
-
-
-## Examples
-
-See the [cookbook on the wiki][wiki-cookbook] for more examples and approaches to specific use-cases.
-
-```php
-<?php
-require 'vendor/autoload.php';
-
-use Ramsey\Uuid\Uuid;
-use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
-
-try {
-
- // Generate a version 1 (time-based) UUID object
- $uuid1 = Uuid::uuid1();
- echo $uuid1->toString() . "\n"; // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd
-
- // Generate a version 3 (name-based and hashed with MD5) UUID object
- $uuid3 = Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net');
- echo $uuid3->toString() . "\n"; // i.e. 11a38b9a-b3da-360f-9353-a5a725514269
-
- // Generate a version 4 (random) UUID object
- $uuid4 = Uuid::uuid4();
- echo $uuid4->toString() . "\n"; // i.e. 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a
-
- // Generate a version 5 (name-based and hashed with SHA1) UUID object
- $uuid5 = Uuid::uuid5(Uuid::NAMESPACE_DNS, 'php.net');
- echo $uuid5->toString() . "\n"; // i.e. c4a760a8-dbcf-5254-a0d9-6a4474bd1b62
-
-} catch (UnsatisfiedDependencyException $e) {
-
- // Some dependency was not met. Either the method cannot be called on a
- // 32-bit system, or it can, but it relies on Moontoast\Math to be present.
- echo 'Caught exception: ' . $e->getMessage() . "\n";
-
-}
-```
-
-
-## Contributing
-
-Contributions are welcome! Please read [CONTRIBUTING][] for details.
-
-
-## Copyright and license
-
-The ramsey/uuid library is copyright © [Ben Ramsey](https://benramsey.com/) and licensed for use under the MIT License (MIT). Please see [LICENSE][] for more information.
-
-
-
-[rfc4122]: http://tools.ietf.org/html/rfc4122
-[conduct]: https://github.com/ramsey/uuid/blob/master/CODE_OF_CONDUCT.md
-[javauuid]: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html
-[pyuuid]: http://docs.python.org/3/library/uuid.html
-[packagist]: https://packagist.org/packages/ramsey/uuid
-[composer]: http://getcomposer.org/
-[moontoast\math]: https://packagist.org/packages/moontoast/math
-[apidocs]: http://docs.benramsey.com/ramsey-uuid/latest/
-[wiki-cookbook]: https://github.com/ramsey/uuid/wiki/Ramsey%5CUuid-Cookbook
-[contributing]: https://github.com/ramsey/uuid/blob/master/CONTRIBUTING.md
-
-[badge-source]: https://img.shields.io/badge/source-ramsey/uuid-blue.svg?style=flat-square
-[badge-release]: https://img.shields.io/packagist/v/ramsey/uuid.svg?style=flat-square
-[badge-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
-[badge-build]: https://img.shields.io/travis/ramsey/uuid/master.svg?style=flat-square
-[badge-coverage]: https://img.shields.io/coveralls/ramsey/uuid/master.svg?style=flat-square
-[badge-downloads]: https://img.shields.io/packagist/dt/ramsey/uuid.svg?style=flat-square
-
-[source]: https://github.com/ramsey/uuid
-[release]: https://packagist.org/packages/ramsey/uuid
-[license]: https://github.com/ramsey/uuid/blob/master/LICENSE
-[build]: https://travis-ci.org/ramsey/uuid
-[coverage]: https://coveralls.io/r/ramsey/uuid?branch=master
-[downloads]: https://packagist.org/packages/ramsey/uuid
+++ /dev/null
-{
- "name": "ramsey/uuid",
- "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).",
- "type": "library",
- "keywords": ["uuid", "identifier", "guid"],
- "homepage": "https://github.com/ramsey/uuid",
- "license": "MIT",
- "authors": [
- {
- "name": "Ben Ramsey",
- "email": "ben@benramsey.com",
- "homepage": "https://benramsey.com"
- },
- {
- "name": "Marijn Huizendveld",
- "email": "marijn.huizendveld@gmail.com"
- },
- {
- "name": "Thibaud Fabre",
- "email": "thibaud@aztech.io"
- }
- ],
- "support": {
- "issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid"
- },
- "require": {
- "php": "^5.4 || ^7.0",
- "paragonie/random_compat": "^1.0|^2.0|9.99.99",
- "symfony/polyfill-ctype": "^1.8"
- },
- "require-dev": {
- "codeception/aspect-mock": "^1.0 | ~2.0.0",
- "doctrine/annotations": "~1.2.0",
- "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ~2.1.0",
- "ircmaxell/random-lib": "^1.1",
- "jakub-onderka/php-parallel-lint": "^0.9.0",
- "mockery/mockery": "^0.9.9",
- "moontoast/math": "^1.1",
- "php-mock/php-mock-phpunit": "^0.3|^1.1",
- "phpunit/phpunit": "^4.7|^5.0|^6.5",
- "squizlabs/php_codesniffer": "^2.3"
- },
- "suggest": {
- "ext-ctype": "Provides support for PHP Ctype functions",
- "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
- "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator",
- "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator",
- "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).",
- "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type.",
- "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid"
- },
- "autoload": {
- "psr-4": {"Ramsey\\Uuid\\": "src/"}
- },
- "autoload-dev": {
- "psr-4": {"Ramsey\\Uuid\\Test\\": "tests/"}
- },
- "replace": {
- "rhumsaa/uuid": "self.version"
- },
- "extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
- }
- },
- "scripts": {
- "lint": "parallel-lint src tests",
- "phpunit": "phpunit --verbose --colors=always",
- "phpcs": "phpcs src tests --standard=psr2 -sp --colors",
- "test": [
- "@lint",
- "@phpunit",
- "@phpcs"
- ]
- },
- "config": {
- "sort-packages": true
- }
-}
+++ /dev/null
-<?php
-
-namespace Ramsey\Uuid;
-
-/**
- * Provides binary math utilities
- */
-class BinaryUtils
-{
- /**
- * Applies the RFC 4122 variant field to the `clock_seq_hi_and_reserved` field
- *
- * @param $clockSeqHi
- * @return int The high field of the clock sequence multiplexed with the variant
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1
- */
- public static function applyVariant($clockSeqHi)
- {
- // Set the variant to RFC 4122
- $clockSeqHi = $clockSeqHi & 0x3f;
- $clockSeqHi &= ~(0xc0);
- $clockSeqHi |= 0x80;
-
- return $clockSeqHi;
- }
-
- /**
- * Applies the RFC 4122 version number to the `time_hi_and_version` field
- *
- * @param string $timeHi
- * @param integer $version
- * @return int The high field of the timestamp multiplexed with the version number
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.3
- */
- public static function applyVersion($timeHi, $version)
- {
- $timeHi = hexdec($timeHi) & 0x0fff;
- $timeHi &= ~(0xf000);
- $timeHi |= $version << 12;
-
- return $timeHi;
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Builder;
-
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Uuid;
-
-/**
- * DefaultUuidBuilder is the default UUID builder for ramsey/uuid; it builds
- * instances of Uuid objects
- */
-class DefaultUuidBuilder implements UuidBuilderInterface
-{
- /**
- * @var NumberConverterInterface
- */
- private $converter;
-
- /**
- * Constructs the DefaultUuidBuilder
- *
- * @param NumberConverterInterface $converter The number converter to use when constructing the Uuid
- */
- public function __construct(NumberConverterInterface $converter)
- {
- $this->converter = $converter;
- }
-
- /**
- * Builds a Uuid
- *
- * @param CodecInterface $codec The codec to use for building this Uuid
- * @param array $fields An array of fields from which to construct the Uuid;
- * see {@see \Ramsey\Uuid\UuidInterface::getFieldsHex()} for array structure.
- * @return Uuid
- */
- public function build(CodecInterface $codec, array $fields)
- {
- return new Uuid($fields, $this->converter, $codec);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Builder;
-
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\DegradedUuid;
-
-/**
- * DegradedUuidBuilder builds instances of DegradedUuid
- */
-class DegradedUuidBuilder implements UuidBuilderInterface
-{
- /**
- * @var NumberConverterInterface
- */
- private $converter;
-
- /**
- * Constructs the DegradedUuidBuilder
- *
- * @param NumberConverterInterface $converter The number converter to use when constructing the DegradedUuid
- */
- public function __construct(NumberConverterInterface $converter)
- {
- $this->converter = $converter;
- }
-
- /**
- * Builds a DegradedUuid
- *
- * @param CodecInterface $codec The codec to use for building this DegradedUuid
- * @param array $fields An array of fields from which to construct the DegradedUuid;
- * see {@see \Ramsey\Uuid\UuidInterface::getFieldsHex()} for array structure.
- * @return DegradedUuid
- */
- public function build(CodecInterface $codec, array $fields)
- {
- return new DegradedUuid($fields, $this->converter, $codec);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Builder;
-
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\UuidInterface;
-
-/**
- * UuidBuilderInterface builds instances UuidInterface
- */
-interface UuidBuilderInterface
-{
- /**
- * Builds an instance of a UuidInterface
- *
- * @param CodecInterface $codec The codec to use for building this UuidInterface instance
- * @param array $fields An array of fields from which to construct a UuidInterface instance;
- * see {@see \Ramsey\Uuid\UuidInterface::getFieldsHex()} for array structure.
- * @return UuidInterface
- */
- public function build(CodecInterface $codec, array $fields);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Codec;
-
-use Ramsey\Uuid\UuidInterface;
-
-/**
- * CodecInterface represents a UUID coder-decoder
- */
-interface CodecInterface
-{
- /**
- * Encodes a UuidInterface as a string representation of a UUID
- *
- * @param UuidInterface $uuid
- * @return string Hexadecimal string representation of a UUID
- */
- public function encode(UuidInterface $uuid);
-
- /**
- * Encodes a UuidInterface as a binary representation of a UUID
- *
- * @param UuidInterface $uuid
- * @return string Binary string representation of a UUID
- */
- public function encodeBinary(UuidInterface $uuid);
-
- /**
- * Decodes a string representation of a UUID into a UuidInterface object instance
- *
- * @param string $encodedUuid
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function decode($encodedUuid);
-
- /**
- * Decodes a binary representation of a UUID into a UuidInterface object instance
- *
- * @param string $bytes
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- * @throws \InvalidArgumentException if string has not 16 characters
- */
- public function decodeBytes($bytes);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Codec;
-
-use Ramsey\Uuid\UuidInterface;
-
-/**
- * GuidStringCodec encodes and decodes globally unique identifiers (GUID)
- *
- * @link https://en.wikipedia.org/wiki/Globally_unique_identifier
- */
-class GuidStringCodec extends StringCodec
-{
- /**
- * Encodes a UuidInterface as a string representation of a GUID
- *
- * @param UuidInterface $uuid
- * @return string Hexadecimal string representation of a GUID
- */
- public function encode(UuidInterface $uuid)
- {
- $components = array_values($uuid->getFieldsHex());
-
- // Swap byte-order on the first three fields
- $this->swapFields($components);
-
- return vsprintf(
- '%08s-%04s-%04s-%02s%02s-%012s',
- $components
- );
- }
-
- /**
- * Encodes a UuidInterface as a binary representation of a GUID
- *
- * @param UuidInterface $uuid
- * @return string Binary string representation of a GUID
- */
- public function encodeBinary(UuidInterface $uuid)
- {
- $components = array_values($uuid->getFieldsHex());
-
- return hex2bin(implode('', $components));
- }
-
- /**
- * Decodes a string representation of a GUID into a UuidInterface object instance
- *
- * @param string $encodedUuid
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function decode($encodedUuid)
- {
- $components = $this->extractComponents($encodedUuid);
-
- $this->swapFields($components);
-
- return $this->getBuilder()->build($this, $this->getFields($components));
- }
-
- /**
- * Decodes a binary representation of a GUID into a UuidInterface object instance
- *
- * @param string $bytes
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function decodeBytes($bytes)
- {
- // Specifically call parent::decode to preserve correct byte order
- return parent::decode(bin2hex($bytes));
- }
-
- /**
- * Swaps fields to support GUID byte order
- *
- * @param array $components An array of UUID components (the UUID exploded on its dashes)
- * @return void
- */
- protected function swapFields(array &$components)
- {
- $hex = unpack('H*', pack('L', hexdec($components[0])));
- $components[0] = $hex[1];
- $hex = unpack('H*', pack('S', hexdec($components[1])));
- $components[1] = $hex[1];
- $hex = unpack('H*', pack('S', hexdec($components[2])));
- $components[2] = $hex[1];
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-namespace Ramsey\Uuid\Codec;
-
-use InvalidArgumentException;
-use Ramsey\Uuid\UuidInterface;
-
-/**
- * OrderedTimeCodec optimizes the bytes to increment UUIDs when time goes by, to improve database INSERTs.
- * The string value will be unchanged from StringCodec. Only works for UUID type 1.
- */
-class OrderedTimeCodec extends StringCodec
-{
-
- /**
- * Encodes a UuidInterface as an optimized binary representation of a UUID
- *
- * @param UuidInterface $uuid
- * @return string Binary string representation of a UUID
- */
- public function encodeBinary(UuidInterface $uuid)
- {
- $fields = $uuid->getFieldsHex();
-
- $optimized = [
- $fields['time_hi_and_version'],
- $fields['time_mid'],
- $fields['time_low'],
- $fields['clock_seq_hi_and_reserved'],
- $fields['clock_seq_low'],
- $fields['node'],
- ];
-
- return hex2bin(implode('', $optimized));
- }
-
- /**
- * Decodes an optimized binary representation of a UUID into a UuidInterface object instance
- *
- * @param string $bytes
- * @return UuidInterface
- * @throws \InvalidArgumentException if string has not 16 characters
- */
- public function decodeBytes($bytes)
- {
- if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException('$bytes string should contain 16 characters.');
- }
-
- $hex = unpack('H*', $bytes)[1];
-
- // Rearrange the fields to their original order
- $hex = substr($hex, 8, 4) . substr($hex, 12, 4) . substr($hex, 4, 4) . substr($hex, 0, 4) . substr($hex, 16);
-
- return $this->decode($hex);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Codec;
-
-use InvalidArgumentException;
-use Ramsey\Uuid\Builder\UuidBuilderInterface;
-use Ramsey\Uuid\Exception\InvalidUuidStringException;
-use Ramsey\Uuid\Uuid;
-use Ramsey\Uuid\UuidInterface;
-
-/**
- * StringCodec encodes and decodes RFC 4122 UUIDs
- *
- * @link http://tools.ietf.org/html/rfc4122
- */
-class StringCodec implements CodecInterface
-{
- /**
- * @var UuidBuilderInterface
- */
- private $builder;
-
- /**
- * Constructs a StringCodec for use encoding and decoding UUIDs
- *
- * @param UuidBuilderInterface $builder The UUID builder to use when encoding UUIDs
- */
- public function __construct(UuidBuilderInterface $builder)
- {
- $this->builder = $builder;
- }
-
- /**
- * Encodes a UuidInterface as a string representation of a UUID
- *
- * @param UuidInterface $uuid
- * @return string Hexadecimal string representation of a UUID
- */
- public function encode(UuidInterface $uuid)
- {
- $fields = array_values($uuid->getFieldsHex());
-
- return vsprintf(
- '%08s-%04s-%04s-%02s%02s-%012s',
- $fields
- );
- }
-
- /**
- * Encodes a UuidInterface as a binary representation of a UUID
- *
- * @param UuidInterface $uuid
- * @return string Binary string representation of a UUID
- */
- public function encodeBinary(UuidInterface $uuid)
- {
- return hex2bin($uuid->getHex());
- }
-
- /**
- * Decodes a string representation of a UUID into a UuidInterface object instance
- *
- * @param string $encodedUuid
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function decode($encodedUuid)
- {
- $components = $this->extractComponents($encodedUuid);
- $fields = $this->getFields($components);
-
- return $this->builder->build($this, $fields);
- }
-
- /**
- * Decodes a binary representation of a UUID into a UuidInterface object instance
- *
- * @param string $bytes
- * @return UuidInterface
- * @throws \InvalidArgumentException if string has not 16 characters
- */
- public function decodeBytes($bytes)
- {
- if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException('$bytes string should contain 16 characters.');
- }
-
- $hexUuid = unpack('H*', $bytes);
-
- return $this->decode($hexUuid[1]);
- }
-
- /**
- * Returns the UUID builder
- *
- * @return UuidBuilderInterface
- */
- protected function getBuilder()
- {
- return $this->builder;
- }
-
- /**
- * Returns an array of UUID components (the UUID exploded on its dashes)
- *
- * @param string $encodedUuid
- * @return array
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- protected function extractComponents($encodedUuid)
- {
- $nameParsed = str_replace(array(
- 'urn:',
- 'uuid:',
- '{',
- '}',
- '-'
- ), '', $encodedUuid);
-
- // We have stripped out the dashes and are breaking up the string using
- // substr(). In this way, we can accept a full hex value that doesn't
- // contain dashes.
- $components = array(
- substr($nameParsed, 0, 8),
- substr($nameParsed, 8, 4),
- substr($nameParsed, 12, 4),
- substr($nameParsed, 16, 4),
- substr($nameParsed, 20)
- );
-
- $nameParsed = implode('-', $components);
-
- if (!Uuid::isValid($nameParsed)) {
- throw new InvalidUuidStringException('Invalid UUID string: ' . $encodedUuid);
- }
-
- return $components;
- }
-
- /**
- * Returns the fields that make up this UUID
- *
- * @see \Ramsey\Uuid\UuidInterface::getFieldsHex()
- * @param array $components
- * @return array
- */
- protected function getFields(array $components)
- {
- return array(
- 'time_low' => str_pad($components[0], 8, '0', STR_PAD_LEFT),
- 'time_mid' => str_pad($components[1], 4, '0', STR_PAD_LEFT),
- 'time_hi_and_version' => str_pad($components[2], 4, '0', STR_PAD_LEFT),
- 'clock_seq_hi_and_reserved' => str_pad(substr($components[3], 0, 2), 2, '0', STR_PAD_LEFT),
- 'clock_seq_low' => str_pad(substr($components[3], 2), 2, '0', STR_PAD_LEFT),
- 'node' => str_pad($components[4], 12, '0', STR_PAD_LEFT)
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-namespace Ramsey\Uuid\Codec;
-
-use Ramsey\Uuid\UuidInterface;
-
-/**
- * TimestampLastCombCodec encodes and decodes COMB UUIDs which have the timestamp as the first 48 bits.
- * To be used with MySQL, PostgreSQL, Oracle.
- */
-class TimestampFirstCombCodec extends StringCodec
-{
- /**
- * Encodes a UuidInterface as a string representation of a timestamp first COMB UUID
- *
- * @param UuidInterface $uuid
- *
- * @return string Hexadecimal string representation of a GUID
- */
- public function encode(UuidInterface $uuid)
- {
- $sixPieceComponents = array_values($uuid->getFieldsHex());
-
- $this->swapTimestampAndRandomBits($sixPieceComponents);
-
- return vsprintf(
- '%08s-%04s-%04s-%02s%02s-%012s',
- $sixPieceComponents
- );
- }
-
- /**
- * Encodes a UuidInterface as a binary representation of timestamp first COMB UUID
- *
- * @param UuidInterface $uuid
- *
- * @return string Binary string representation of timestamp first COMB UUID
- */
- public function encodeBinary(UuidInterface $uuid)
- {
- $stringEncoding = $this->encode($uuid);
-
- return hex2bin(str_replace('-', '', $stringEncoding));
- }
-
- /**
- * Decodes a string representation of timestamp first COMB UUID into a UuidInterface object instance
- *
- * @param string $encodedUuid
- *
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function decode($encodedUuid)
- {
- $fivePieceComponents = $this->extractComponents($encodedUuid);
-
- $this->swapTimestampAndRandomBits($fivePieceComponents);
-
- return $this->getBuilder()->build($this, $this->getFields($fivePieceComponents));
- }
-
- /**
- * Decodes a binary representation of timestamp first COMB UUID into a UuidInterface object instance
- *
- * @param string $bytes
- *
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function decodeBytes($bytes)
- {
- return $this->decode(bin2hex($bytes));
- }
-
- /**
- * Swaps the first 48 bits with the last 48 bits
- *
- * @param array $components An array of UUID components (the UUID exploded on its dashes)
- *
- * @return void
- */
- protected function swapTimestampAndRandomBits(array &$components)
- {
- $last48Bits = $components[4];
- if (count($components) == 6) {
- $last48Bits = $components[5];
- $components[5] = $components[0] . $components[1];
- } else {
- $components[4] = $components[0] . $components[1];
- }
-
- $components[0] = substr($last48Bits, 0, 8);
- $components[1] = substr($last48Bits, 8, 4);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-namespace Ramsey\Uuid\Codec;
-
-/**
- * TimestampLastCombCodec encodes and decodes COMB UUIDs which have the timestamp as the last 48 bits.
- * To be used with MSSQL.
- */
-class TimestampLastCombCodec extends StringCodec
-{
-
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter\Number;
-
-use Moontoast\Math\BigNumber;
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-
-/**
- * BigNumberConverter converts UUIDs from hexadecimal characters into
- * moontoast/math `BigNumber` representations of integers and vice versa
- */
-class BigNumberConverter implements NumberConverterInterface
-{
- /**
- * Converts a hexadecimal number into a `Moontoast\Math\BigNumber` representation
- *
- * @param string $hex The hexadecimal string representation to convert
- * @return BigNumber
- */
- public function fromHex($hex)
- {
- $number = BigNumber::convertToBase10($hex, 16);
-
- return new BigNumber($number);
- }
-
- /**
- * Converts an integer or `Moontoast\Math\BigNumber` integer representation
- * into a hexadecimal string representation
- *
- * @param int|string|BigNumber $integer An integer or `Moontoast\Math\BigNumber`
- * @return string Hexadecimal string
- */
- public function toHex($integer)
- {
- if (!$integer instanceof BigNumber) {
- $integer = new BigNumber($integer);
- }
-
- return BigNumber::convertFromBase10($integer, 16);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter\Number;
-
-use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-
-/**
- * DegradedNumberConverter throws `UnsatisfiedDependencyException` exceptions
- * if attempting to use number conversion functionality in an environment that
- * does not support large integers (i.e. when moontoast/math is not available)
- */
-class DegradedNumberConverter implements NumberConverterInterface
-{
- /**
- * Throws an `UnsatisfiedDependencyException`
- *
- * @param string $hex The hexadecimal string representation to convert
- * @return void
- * @throws UnsatisfiedDependencyException
- */
- public function fromHex($hex)
- {
- throw new UnsatisfiedDependencyException(
- 'Cannot call ' . __METHOD__ . ' without support for large '
- . 'integers, since integer is an unsigned '
- . '128-bit integer; Moontoast\Math\BigNumber is required.'
- );
- }
-
- /**
- * Throws an `UnsatisfiedDependencyException`
- *
- * @param mixed $integer An integer representation to convert
- * @return void
- * @throws UnsatisfiedDependencyException
- */
- public function toHex($integer)
- {
- throw new UnsatisfiedDependencyException(
- 'Cannot call ' . __METHOD__ . ' without support for large '
- . 'integers, since integer is an unsigned '
- . '128-bit integer; Moontoast\Math\BigNumber is required. '
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter;
-
-/**
- * NumberConverterInterface converts UUIDs from hexadecimal characters into
- * representations of integers and vice versa
- */
-interface NumberConverterInterface
-{
- /**
- * Converts a hexadecimal number into an integer representation of the number
- *
- * The integer representation returned may be an object or a string
- * representation of the integer, depending on the implementation.
- *
- * @param string $hex The hexadecimal string representation to convert
- * @return mixed
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- */
- public function fromHex($hex);
-
- /**
- * Converts an integer representation into a hexadecimal string representation
- * of the number
- *
- * @param mixed $integer An integer representation to convert; this may be
- * a true integer, a string integer, or a object representation that
- * this converter can understand
- * @return string Hexadecimal string
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- */
- public function toHex($integer);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter\Time;
-
-use Moontoast\Math\BigNumber;
-use Ramsey\Uuid\Converter\TimeConverterInterface;
-
-/**
- * BigNumberTimeConverter uses the moontoast/math library's `BigNumber` to
- * provide facilities for converting parts of time into representations that may
- * be used in UUIDs
- */
-class BigNumberTimeConverter implements TimeConverterInterface
-{
- /**
- * Uses the provided seconds and micro-seconds to calculate the time_low,
- * time_mid, and time_high fields used by RFC 4122 version 1 UUIDs
- *
- * @param string $seconds
- * @param string $microSeconds
- * @return string[] An array containing `low`, `mid`, and `high` keys
- * @link http://tools.ietf.org/html/rfc4122#section-4.2.2
- */
- public function calculateTime($seconds, $microSeconds)
- {
- $uuidTime = new BigNumber('0');
-
- $sec = new BigNumber($seconds);
- $sec->multiply('10000000');
-
- $usec = new BigNumber($microSeconds);
- $usec->multiply('10');
-
- $uuidTime->add($sec)
- ->add($usec)
- ->add('122192928000000000');
-
- $uuidTimeHex = sprintf('%016s', $uuidTime->convertToBase(16));
-
- return array(
- 'low' => substr($uuidTimeHex, 8),
- 'mid' => substr($uuidTimeHex, 4, 4),
- 'hi' => substr($uuidTimeHex, 0, 4),
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter\Time;
-
-use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
-
-/**
- * DegradedTimeConverter throws `UnsatisfiedDependencyException` exceptions
- * if attempting to use time conversion functionality in an environment that
- * does not support large integers (i.e. when moontoast/math is not available)
- */
-class DegradedTimeConverter implements TimeConverterInterface
-{
- /**
- * Throws an `UnsatisfiedDependencyException`
- *
- * @param string $seconds
- * @param string $microSeconds
- * @return void
- * @throws UnsatisfiedDependencyException if called on a 32-bit system and `Moontoast\Math\BigNumber` is not present
- */
- public function calculateTime($seconds, $microSeconds)
- {
- throw new UnsatisfiedDependencyException(
- 'When calling ' . __METHOD__ . ' on a 32-bit system, '
- . 'Moontoast\Math\BigNumber must be present.'
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter\Time;
-
-use Ramsey\Uuid\Converter\TimeConverterInterface;
-
-/**
- * PhpTimeConverter uses built-in PHP functions and standard math operations
- * available to the PHP programming language to provide facilities for
- * converting parts of time into representations that may be used in UUIDs
- */
-class PhpTimeConverter implements TimeConverterInterface
-{
- /**
- * Uses the provided seconds and micro-seconds to calculate the time_low,
- * time_mid, and time_high fields used by RFC 4122 version 1 UUIDs
- *
- * @param string $seconds
- * @param string $microSeconds
- * @return string[] An array containing `low`, `mid`, and `high` keys
- * @link http://tools.ietf.org/html/rfc4122#section-4.2.2
- */
- public function calculateTime($seconds, $microSeconds)
- {
- // 0x01b21dd213814000 is the number of 100-ns intervals between the
- // UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
- $uuidTime = ($seconds * 10000000) + ($microSeconds * 10) + 0x01b21dd213814000;
-
- return array(
- 'low' => sprintf('%08x', $uuidTime & 0xffffffff),
- 'mid' => sprintf('%04x', ($uuidTime >> 32) & 0xffff),
- 'hi' => sprintf('%04x', ($uuidTime >> 48) & 0x0fff),
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Converter;
-
-/**
- * TimeConverterInterface provides facilities for converting parts of time into
- * representations that may be used in UUIDs
- */
-interface TimeConverterInterface
-{
- /**
- * Uses the provided seconds and micro-seconds to calculate the time_low,
- * time_mid, and time_high fields used by RFC 4122 version 1 UUIDs
- *
- * @param string $seconds
- * @param string $microSeconds
- * @return string[] An array guaranteed to contain `low`, `mid`, and `high` keys
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if called on a 32-bit system and
- * `Moontoast\Math\BigNumber` is not present
- * @link http://tools.ietf.org/html/rfc4122#section-4.2.2
- */
- public function calculateTime($seconds, $microSeconds);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid;
-
-use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
-use Ramsey\Uuid\Exception\UnsupportedOperationException;
-
-/**
- * DegradedUuid represents an RFC 4122 UUID on 32-bit systems
- *
- * @see Uuid
- */
-class DegradedUuid extends Uuid
-{
- /**
- * @inheritdoc
- */
- public function getDateTime()
- {
- if ($this->getVersion() != 1) {
- throw new UnsupportedOperationException('Not a time-based UUID');
- }
-
- $time = $this->converter->fromHex($this->getTimestampHex());
-
- $ts = new \Moontoast\Math\BigNumber($time, 20);
- $ts->subtract('122192928000000000');
- $ts->divide('10000000.0');
- $ts->round();
- $unixTime = $ts->getValue();
-
- return new \DateTime("@{$unixTime}");
- }
-
- /**
- * For degraded UUIDs, throws an `UnsatisfiedDependencyException` when
- * called on a 32-bit system
- *
- * @throws UnsatisfiedDependencyException if called on a 32-bit system
- */
- public function getFields()
- {
- throw new UnsatisfiedDependencyException(
- 'Cannot call ' . __METHOD__ . ' on a 32-bit system, since some '
- . 'values overflow the system max integer value'
- . '; consider calling getFieldsHex instead'
- );
- }
-
- /**
- * For degraded UUIDs, throws an `UnsatisfiedDependencyException` when
- * called on a 32-bit system
- *
- * @throws UnsatisfiedDependencyException if called on a 32-bit system
- */
- public function getNode()
- {
- throw new UnsatisfiedDependencyException(
- 'Cannot call ' . __METHOD__ . ' on a 32-bit system, since node '
- . 'is an unsigned 48-bit integer and can overflow the system '
- . 'max integer value'
- . '; consider calling getNodeHex instead'
- );
- }
-
- /**
- * For degraded UUIDs, throws an `UnsatisfiedDependencyException` when
- * called on a 32-bit system
- *
- * @throws UnsatisfiedDependencyException if called on a 32-bit system
- */
- public function getTimeLow()
- {
- throw new UnsatisfiedDependencyException(
- 'Cannot call ' . __METHOD__ . ' on a 32-bit system, since time_low '
- . 'is an unsigned 32-bit integer and can overflow the system '
- . 'max integer value'
- . '; consider calling getTimeLowHex instead'
- );
- }
-
- /**
- * For degraded UUIDs, throws an `UnsatisfiedDependencyException` when
- * called on a 32-bit system
- *
- * @throws UnsatisfiedDependencyException if called on a 32-bit system
- * @throws UnsupportedOperationException If this UUID is not a version 1 UUID
- */
- public function getTimestamp()
- {
- if ($this->getVersion() != 1) {
- throw new UnsupportedOperationException('Not a time-based UUID');
- }
-
- throw new UnsatisfiedDependencyException(
- 'Cannot call ' . __METHOD__ . ' on a 32-bit system, since timestamp '
- . 'is an unsigned 60-bit integer and can overflow the system '
- . 'max integer value'
- . '; consider calling getTimestampHex instead'
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Exception;
-
-/**
- * Thrown to indicate that the parsed UUID string is invalid.
- */
-class InvalidUuidStringException extends \InvalidArgumentException
-{
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Exception;
-
-/**
- * Thrown to indicate that the requested operation has dependencies that have not
- * been satisfied.
- */
-class UnsatisfiedDependencyException extends \RuntimeException
-{
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Exception;
-
-/**
- * Thrown to indicate that the requested operation is not supported.
- */
-class UnsupportedOperationException extends \RuntimeException
-{
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid;
-
-use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Generator\PeclUuidTimeGenerator;
-use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
-use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
-use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Converter\Number\BigNumberConverter;
-use Ramsey\Uuid\Converter\Number\DegradedNumberConverter;
-use Ramsey\Uuid\Converter\Time\BigNumberTimeConverter;
-use Ramsey\Uuid\Converter\Time\DegradedTimeConverter;
-use Ramsey\Uuid\Converter\Time\PhpTimeConverter;
-use Ramsey\Uuid\Provider\Time\SystemTimeProvider;
-use Ramsey\Uuid\Builder\UuidBuilderInterface;
-use Ramsey\Uuid\Builder\DefaultUuidBuilder;
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\Codec\StringCodec;
-use Ramsey\Uuid\Codec\GuidStringCodec;
-use Ramsey\Uuid\Builder\DegradedUuidBuilder;
-use Ramsey\Uuid\Generator\RandomGeneratorFactory;
-use Ramsey\Uuid\Generator\RandomGeneratorInterface;
-use Ramsey\Uuid\Generator\TimeGeneratorFactory;
-use Ramsey\Uuid\Generator\TimeGeneratorInterface;
-use Ramsey\Uuid\Provider\TimeProviderInterface;
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-
-/**
- * FeatureSet detects and exposes available features in the current environment
- * (32- or 64-bit, available dependencies, etc.)
- */
-class FeatureSet
-{
- /**
- * @var bool
- */
- private $disableBigNumber = false;
-
- /**
- * @var bool
- */
- private $disable64Bit = false;
-
- /**
- * @var bool
- */
- private $ignoreSystemNode = false;
-
- /**
- * @var bool
- */
- private $enablePecl = false;
-
- /**
- * @var UuidBuilderInterface
- */
- private $builder;
-
- /**
- * @var CodecInterface
- */
- private $codec;
-
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * Constructs a `FeatureSet` for use by a `UuidFactory` to determine or set
- * features available to the environment
- *
- * @param bool $useGuids Whether to build UUIDs using the `GuidStringCodec`
- * @param bool $force32Bit Whether to force the use of 32-bit functionality
- * (primarily for testing purposes)
- * @param bool $forceNoBigNumber Whether to disable the use of moontoast/math
- * `BigNumber` (primarily for testing purposes)
- * @param bool $ignoreSystemNode Whether to disable attempts to check for
- * the system host ID (primarily for testing purposes)
- * @param bool $enablePecl Whether to enable the use of the `PeclUuidTimeGenerator`
- * to generate version 1 UUIDs
- */
- public function __construct(
- $useGuids = false,
- $force32Bit = false,
- $forceNoBigNumber = false,
- $ignoreSystemNode = false,
- $enablePecl = false
- ) {
- $this->disableBigNumber = $forceNoBigNumber;
- $this->disable64Bit = $force32Bit;
- $this->ignoreSystemNode = $ignoreSystemNode;
- $this->enablePecl = $enablePecl;
-
- $this->numberConverter = $this->buildNumberConverter();
- $this->builder = $this->buildUuidBuilder();
- $this->codec = $this->buildCodec($useGuids);
- $this->nodeProvider = $this->buildNodeProvider();
- $this->randomGenerator = $this->buildRandomGenerator();
- $this->setTimeProvider(new SystemTimeProvider());
- }
-
- /**
- * Returns the builder configured for this environment
- *
- * @return UuidBuilderInterface
- */
- public function getBuilder()
- {
- return $this->builder;
- }
-
- /**
- * Returns the UUID UUID coder-decoder configured for this environment
- *
- * @return CodecInterface
- */
- public function getCodec()
- {
- return $this->codec;
- }
-
- /**
- * Returns the system node ID provider configured for this environment
- *
- * @return NodeProviderInterface
- */
- public function getNodeProvider()
- {
- return $this->nodeProvider;
- }
-
- /**
- * Returns the number converter configured for this environment
- *
- * @return NumberConverterInterface
- */
- public function getNumberConverter()
- {
- return $this->numberConverter;
- }
-
- /**
- * Returns the random UUID generator configured for this environment
- *
- * @return RandomGeneratorInterface
- */
- public function getRandomGenerator()
- {
- return $this->randomGenerator;
- }
-
- /**
- * Returns the time-based UUID generator configured for this environment
- *
- * @return TimeGeneratorInterface
- */
- public function getTimeGenerator()
- {
- return $this->timeGenerator;
- }
-
- /**
- * Sets the time provider for use in this environment
- *
- * @param TimeProviderInterface $timeProvider
- */
- public function setTimeProvider(TimeProviderInterface $timeProvider)
- {
- $this->timeGenerator = $this->buildTimeGenerator($timeProvider);
- }
-
- /**
- * Determines which UUID coder-decoder to use and returns the configured
- * codec for this environment
- *
- * @param bool $useGuids Whether to build UUIDs using the `GuidStringCodec`
- * @return CodecInterface
- */
- protected function buildCodec($useGuids = false)
- {
- if ($useGuids) {
- return new GuidStringCodec($this->builder);
- }
-
- return new StringCodec($this->builder);
- }
-
- /**
- * Determines which system node ID provider to use and returns the configured
- * system node ID provider for this environment
- *
- * @return NodeProviderInterface
- */
- protected function buildNodeProvider()
- {
- if ($this->ignoreSystemNode) {
- return new RandomNodeProvider();
- }
-
- return new FallbackNodeProvider([
- new SystemNodeProvider(),
- new RandomNodeProvider()
- ]);
- }
-
- /**
- * Determines which number converter to use and returns the configured
- * number converter for this environment
- *
- * @return NumberConverterInterface
- */
- protected function buildNumberConverter()
- {
- if ($this->hasBigNumber()) {
- return new BigNumberConverter();
- }
-
- return new DegradedNumberConverter();
- }
-
- /**
- * Determines which random UUID generator to use and returns the configured
- * random UUID generator for this environment
- *
- * @return RandomGeneratorInterface
- */
- protected function buildRandomGenerator()
- {
- return (new RandomGeneratorFactory())->getGenerator();
- }
-
- /**
- * Determines which time-based UUID generator to use and returns the configured
- * time-based UUID generator for this environment
- *
- * @param TimeProviderInterface $timeProvider
- * @return TimeGeneratorInterface
- */
- protected function buildTimeGenerator(TimeProviderInterface $timeProvider)
- {
- if ($this->enablePecl) {
- return new PeclUuidTimeGenerator();
- }
-
- return (new TimeGeneratorFactory(
- $this->nodeProvider,
- $this->buildTimeConverter(),
- $timeProvider
- ))->getGenerator();
- }
-
- /**
- * Determines which time converter to use and returns the configured
- * time converter for this environment
- *
- * @return TimeConverterInterface
- */
- protected function buildTimeConverter()
- {
- if ($this->is64BitSystem()) {
- return new PhpTimeConverter();
- } elseif ($this->hasBigNumber()) {
- return new BigNumberTimeConverter();
- }
-
- return new DegradedTimeConverter();
- }
-
- /**
- * Determines which UUID builder to use and returns the configured UUID
- * builder for this environment
- *
- * @return UuidBuilderInterface
- */
- protected function buildUuidBuilder()
- {
- if ($this->is64BitSystem()) {
- return new DefaultUuidBuilder($this->numberConverter);
- }
-
- return new DegradedUuidBuilder($this->numberConverter);
- }
-
- /**
- * Returns true if the system has `Moontoast\Math\BigNumber`
- *
- * @return bool
- */
- protected function hasBigNumber()
- {
- return class_exists('Moontoast\Math\BigNumber') && !$this->disableBigNumber;
- }
-
- /**
- * Returns true if the system is 64-bit, false otherwise
- *
- * @return bool
- */
- protected function is64BitSystem()
- {
- return PHP_INT_SIZE == 8 && !$this->disable64Bit;
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-
-/**
- * CombGenerator provides functionality to generate COMB (combined GUID/timestamp)
- * sequential UUIDs
- *
- * @link https://en.wikipedia.org/wiki/Globally_unique_identifier#Sequential_algorithms
- */
-class CombGenerator implements RandomGeneratorInterface
-{
- const TIMESTAMP_BYTES = 6;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var NumberConverterInterface
- */
- private $converter;
-
- /**
- * Constructs a `CombGenerator` using a random-number generator and a number converter
- *
- * @param RandomGeneratorInterface $generator Random-number generator for the non-time part.
- * @param NumberConverterInterface $numberConverter Instance of number converter.
- */
- public function __construct(RandomGeneratorInterface $generator, NumberConverterInterface $numberConverter)
- {
- $this->converter = $numberConverter;
- $this->randomGenerator = $generator;
- }
-
- /**
- * Generates a string of binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException if length is not a positive integer
- * @throws \Exception
- */
- public function generate($length)
- {
- if ($length < self::TIMESTAMP_BYTES || $length < 0) {
- throw new \InvalidArgumentException('Length must be a positive integer.');
- }
-
- $hash = '';
-
- if (self::TIMESTAMP_BYTES > 0 && $length > self::TIMESTAMP_BYTES) {
- $hash = $this->randomGenerator->generate($length - self::TIMESTAMP_BYTES);
- }
-
- $lsbTime = str_pad($this->converter->toHex($this->timestamp()), self::TIMESTAMP_BYTES * 2, '0', STR_PAD_LEFT);
-
- return hex2bin(str_pad(bin2hex($hash), $length - self::TIMESTAMP_BYTES, '0') . $lsbTime);
- }
-
- /**
- * Returns current timestamp as integer, precise to 0.00001 seconds
- *
- * @return string
- */
- private function timestamp()
- {
- $time = explode(' ', microtime(false));
-
- return $time[1] . substr($time[0], 2, 5);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-use Ramsey\Uuid\BinaryUtils;
-use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-use Ramsey\Uuid\Provider\TimeProviderInterface;
-
-/**
- * DefaultTimeGenerator provides functionality to generate strings of binary
- * data for version 1 UUIDs based on a host ID, sequence number, and the current
- * time
- */
-class DefaultTimeGenerator implements TimeGeneratorInterface
-{
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
- /**
- * Constructs a `DefaultTimeGenerator` using a node provider, time converter,
- * and time provider
- *
- * @param NodeProviderInterface $nodeProvider
- * @param TimeConverterInterface $timeConverter
- * @param TimeProviderInterface $timeProvider
- */
- public function __construct(
- NodeProviderInterface $nodeProvider,
- TimeConverterInterface $timeConverter,
- TimeProviderInterface $timeProvider
- ) {
- $this->nodeProvider = $nodeProvider;
- $this->timeConverter = $timeConverter;
- $this->timeProvider = $timeProvider;
- }
-
- /**
- * Generate a version 1 UUID from a host ID, sequence number, and the current time
- *
- * If $node is not given, we will attempt to obtain the local hardware
- * address. If $clockSeq is given, it is used as the sequence number;
- * otherwise a random 14-bit sequence number is chosen.
- *
- * @param int|string $node A 48-bit number representing the hardware address
- * This number may be represented as an integer or a hexadecimal string.
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes.
- * @return string A binary string
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if called on a 32-bit system and
- * `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function generate($node = null, $clockSeq = null)
- {
- $node = $this->getValidNode($node);
-
- if ($clockSeq === null) {
- // Not using "stable storage"; see RFC 4122, Section 4.2.1.1
- $clockSeq = random_int(0, 0x3fff);
- }
-
- // Create a 60-bit time value as a count of 100-nanosecond intervals
- // since 00:00:00.00, 15 October 1582
- $timeOfDay = $this->timeProvider->currentTime();
- $uuidTime = $this->timeConverter->calculateTime($timeOfDay['sec'], $timeOfDay['usec']);
-
- $timeHi = BinaryUtils::applyVersion($uuidTime['hi'], 1);
- $clockSeqHi = BinaryUtils::applyVariant($clockSeq >> 8);
-
- $hex = vsprintf(
- '%08s%04s%04s%02s%02s%012s',
- array(
- $uuidTime['low'],
- $uuidTime['mid'],
- sprintf('%04x', $timeHi),
- sprintf('%02x', $clockSeqHi),
- sprintf('%02x', $clockSeq & 0xff),
- $node,
- )
- );
-
- return hex2bin($hex);
- }
-
- /**
- * Uses the node provider given when constructing this instance to get
- * the node ID (usually a MAC address)
- *
- * @param string|int $node A node value that may be used to override the node provider
- * @return string Hexadecimal representation of the node ID
- * @throws \InvalidArgumentException
- * @throws \Exception
- */
- protected function getValidNode($node)
- {
- if ($node === null) {
- $node = $this->nodeProvider->getNode();
- }
-
- // Convert the node to hex, if it is still an integer
- if (is_int($node)) {
- $node = sprintf('%012x', $node);
- }
-
- if (!ctype_xdigit($node) || strlen($node) > 12) {
- throw new \InvalidArgumentException('Invalid node value');
- }
-
- return strtolower(sprintf('%012s', $node));
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * MtRandRandomGenerator provides functionality to generate strings of random
- * binary data using the `mt_rand()` PHP function
- *
- * @link http://php.net/mt_rand
- */
-class MtRandGenerator implements RandomGeneratorInterface
-{
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- */
- public function generate($length)
- {
- $bytes = '';
-
- for ($i = 1; $i <= $length; $i++) {
- $bytes = chr(mt_rand(0, 255)) . $bytes;
- }
-
- return $bytes;
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * OpenSslRandomGenerator provides functionality to generate strings of random
- * binary data using the `openssl_random_pseudo_bytes()` PHP function
- *
- * The use of this generator requires PHP to be compiled using the
- * `--with-openssl` option.
- *
- * @link http://php.net/openssl_random_pseudo_bytes
- */
-class OpenSslGenerator implements RandomGeneratorInterface
-{
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- */
- public function generate($length)
- {
- return openssl_random_pseudo_bytes($length);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * PeclUuidRandomGenerator provides functionality to generate strings of random
- * binary data using the PECL UUID PHP extension
- *
- * @link https://pecl.php.net/package/uuid
- */
-class PeclUuidRandomGenerator implements RandomGeneratorInterface
-{
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- */
- public function generate($length)
- {
- $uuid = uuid_create(UUID_TYPE_RANDOM);
-
- return uuid_parse($uuid);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * PeclUuidTimeGenerator provides functionality to generate strings of binary
- * data for version 1 UUIDs using the PECL UUID PHP extension
- *
- * @link https://pecl.php.net/package/uuid
- */
-class PeclUuidTimeGenerator implements TimeGeneratorInterface
-{
- /**
- * Generate a version 1 UUID using the PECL UUID extension
- *
- * @param int|string $node Not used in this context
- * @param int $clockSeq Not used in this context
- * @return string A binary string
- */
- public function generate($node = null, $clockSeq = null)
- {
- $uuid = uuid_create(UUID_TYPE_TIME);
-
- return uuid_parse($uuid);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * RandomBytesGenerator provides functionality to generate strings of random
- * binary data using `random_bytes()` function in PHP 7+ or paragonie/random_compat
- *
- * @link http://php.net/random_bytes
- * @link https://github.com/paragonie/random_compat
- */
-class RandomBytesGenerator implements RandomGeneratorInterface
-{
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function generate($length)
- {
- return random_bytes($length);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * A factory for retrieving a random generator, based on the environment
- */
-class RandomGeneratorFactory
-{
- /**
- * Returns a default random generator, based on the current environment
- *
- * @return RandomGeneratorInterface
- */
- public static function getGenerator()
- {
- return new RandomBytesGenerator();
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * RandomGeneratorInterface provides functionality to generate strings of random
- * binary data
- */
-interface RandomGeneratorInterface
-{
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function generate($length);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-use RandomLib\Generator;
-use RandomLib\Factory;
-
-/**
- * RandomLibAdapter provides functionality to generate strings of random
- * binary data using the ircmaxell/random-lib library
- *
- * @link https://packagist.org/packages/ircmaxell/random-lib
- */
-class RandomLibAdapter implements RandomGeneratorInterface
-{
- /**
- * @var Generator
- */
- private $generator;
-
- /**
- * Constructs a `RandomLibAdapter` using a `RandomLib\Generator`
- *
- * By default, if no `Generator` is passed in, this creates a medium-strength
- * generator to use when generating random binary data.
- *
- * @param Generator $generator An ircmaxell/random-lib `Generator`
- */
- public function __construct(Generator $generator = null)
- {
- $this->generator = $generator;
-
- if ($this->generator === null) {
- $factory = new Factory();
-
- $this->generator = $factory->getMediumStrengthGenerator();
- }
- }
-
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- */
- public function generate($length)
- {
- return $this->generator->generate($length);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * SodiumRandomGenerator provides functionality to generate strings of random
- * binary data using the PECL libsodium extension
- *
- * @link http://pecl.php.net/package/libsodium
- * @link https://paragonie.com/book/pecl-libsodium
- */
-class SodiumRandomGenerator implements RandomGeneratorInterface
-{
- /**
- * Generates a string of random binary data of the specified length
- *
- * @param integer $length The number of bytes of random binary data to generate
- * @return string A binary string
- */
- public function generate($length)
- {
- return \Sodium\randombytes_buf($length);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-use Ramsey\Uuid\Provider\TimeProviderInterface;
-
-/**
- * A factory for retrieving a time generator, based on the environment
- */
-class TimeGeneratorFactory
-{
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
- /**
- * Constructs a `TimeGeneratorFactory` using a node provider, time converter,
- * and time provider
- *
- * @param NodeProviderInterface $nodeProvider
- * @param TimeConverterInterface $timeConverter
- * @param TimeProviderInterface $timeProvider
- */
- public function __construct(
- NodeProviderInterface $nodeProvider,
- TimeConverterInterface $timeConverter,
- TimeProviderInterface $timeProvider
- ) {
- $this->nodeProvider = $nodeProvider;
- $this->timeConverter = $timeConverter;
- $this->timeProvider = $timeProvider;
- }
-
- /**
- * Returns a default time generator, based on the current environment
- *
- * @return TimeGeneratorInterface
- */
- public function getGenerator()
- {
- return new DefaultTimeGenerator(
- $this->nodeProvider,
- $this->timeConverter,
- $this->timeProvider
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Generator;
-
-/**
- * TimeGeneratorInterface provides functionality to generate strings of binary
- * data for version 1 UUIDs based on a host ID, sequence number, and the current
- * time
- */
-interface TimeGeneratorInterface
-{
- /**
- * Generate a version 1 UUID from a host ID, sequence number, and the current time
- *
- * @param int|string $node A 48-bit number representing the hardware address
- * This number may be represented as an integer or a hexadecimal string.
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes.
- * @return string A binary string
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if called on a 32-bit system and
- * `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function generate($node = null, $clockSeq = null);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider\Node;
-
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-
-/**
- * FallbackNodeProvider attempts to gain the system host ID from an array of
- * providers, falling back to the next in line in the event a host ID can not be
- * obtained
- */
-class FallbackNodeProvider implements NodeProviderInterface
-{
- /**
- * @var NodeProviderInterface[]
- */
- private $nodeProviders;
-
- /**
- * Constructs a `FallbackNodeProvider` using an array of node providers
- *
- * @param NodeProviderInterface[] $providers Array of node providers
- */
- public function __construct(array $providers)
- {
- $this->nodeProviders = $providers;
- }
-
- /**
- * Returns the system node ID by iterating over an array of node providers
- * and returning the first non-empty value found
- *
- * @return string System node ID as a hexadecimal string
- * @throws \Exception
- */
- public function getNode()
- {
- foreach ($this->nodeProviders as $provider) {
- if ($node = $provider->getNode()) {
- return $node;
- }
- }
-
- return null;
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider\Node;
-
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-
-/**
- * RandomNodeProvider provides functionality to generate a random node ID, in
- * the event that the node ID could not be obtained from the host system
- *
- * @link http://tools.ietf.org/html/rfc4122#section-4.5
- */
-class RandomNodeProvider implements NodeProviderInterface
-{
- /**
- * Returns the system node ID
- *
- * @return string System node ID as a hexadecimal string
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function getNode()
- {
- $node = hexdec(bin2hex(random_bytes(6)));
-
- // Set the multicast bit; see RFC 4122, section 4.5.
- $node = $node | 0x010000000000;
-
- return str_pad(dechex($node), 12, '0', STR_PAD_LEFT);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider\Node;
-
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-
-/**
- * SystemNodeProvider provides functionality to get the system node ID (MAC
- * address) using external system calls
- */
-class SystemNodeProvider implements NodeProviderInterface
-{
- /**
- * Returns the system node ID
- *
- * @return string|false System node ID as a hexadecimal string, or false if it is not found
- */
- public function getNode()
- {
- static $node = null;
-
- if ($node !== null) {
- return $node;
- }
-
- $pattern = '/[^:]([0-9A-Fa-f]{2}([:-])[0-9A-Fa-f]{2}(\2[0-9A-Fa-f]{2}){4})[^:]/';
- $matches = array();
-
- // first try a linux specific way
- $node = $this->getSysfs();
-
- // Search the ifconfig output for all MAC addresses and return
- // the first one found
- if ($node === false) {
- if (preg_match_all($pattern, $this->getIfconfig(), $matches, PREG_PATTERN_ORDER)) {
- $node = $matches[1][0];
- }
- }
- if ($node !== false) {
- $node = str_replace([':', '-'], '', $node);
- }
- return $node;
- }
-
- /**
- * Returns the network interface configuration for the system
- *
- * @codeCoverageIgnore
- * @return string
- */
- protected function getIfconfig()
- {
- if (strpos(strtolower(ini_get('disable_functions')), 'passthru') !== false) {
- return '';
- }
-
- ob_start();
- switch (strtoupper(substr(php_uname('a'), 0, 3))) {
- case 'WIN':
- passthru('ipconfig /all 2>&1');
- break;
- case 'DAR':
- passthru('ifconfig 2>&1');
- break;
- case 'FRE':
- passthru('netstat -i -f link 2>&1');
- break;
- case 'LIN':
- default:
- passthru('netstat -ie 2>&1');
- break;
- }
-
- return ob_get_clean();
- }
-
- /**
- * Returns mac address from the first system interface via the sysfs interface
- *
- * @return string|bool
- */
- protected function getSysfs()
- {
- $mac = false;
-
- if (strtoupper(php_uname('s')) === 'LINUX') {
- $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);
-
- if (empty($addressPaths)) {
- return false;
- }
-
- array_walk($addressPaths, function ($addressPath) use (&$macs) {
- $macs[] = file_get_contents($addressPath);
- });
-
- $macs = array_map('trim', $macs);
-
- // remove invalid entries
- $macs = array_filter($macs, function ($mac) {
- return
- // localhost adapter
- $mac !== '00:00:00:00:00:00' &&
- // must match mac adress
- preg_match('/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i', $mac);
- });
-
- $mac = reset($macs);
- }
-
- return $mac;
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider;
-
-/**
- * NodeProviderInterface provides functionality to get the node ID (or host ID
- * in the form of the system's MAC address) from a specific type of node provider
- */
-interface NodeProviderInterface
-{
- /**
- * Returns the system node ID
- *
- * @return string System node ID as a hexadecimal string
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function getNode();
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider\Time;
-
-use Ramsey\Uuid\Provider\TimeProviderInterface;
-
-/**
- * FixedTimeProvider uses an previously-generated timestamp to provide the time
- *
- * This provider allows the use of a previously-generated timestamp, such as one
- * stored in a database, when creating version 1 UUIDs.
- */
-class FixedTimeProvider implements TimeProviderInterface
-{
- /**
- * @var int[] Array containing `sec` and `usec` components of a timestamp
- */
- private $fixedTime;
-
- /**
- * Constructs a `FixedTimeProvider` using the provided `$timestamp`
- *
- * @param int[] Array containing `sec` and `usec` components of a timestamp
- * @throws \InvalidArgumentException if the `$timestamp` does not contain `sec` or `usec` components
- */
- public function __construct(array $timestamp)
- {
- if (!array_key_exists('sec', $timestamp) || !array_key_exists('usec', $timestamp)) {
- throw new \InvalidArgumentException('Array must contain sec and usec keys.');
- }
-
- $this->fixedTime = $timestamp;
- }
-
- /**
- * Sets the `usec` component of the timestamp
- *
- * @param int $value The `usec` value to set
- */
- public function setUsec($value)
- {
- $this->fixedTime['usec'] = $value;
- }
-
- /**
- * Sets the `sec` component of the timestamp
- *
- * @param int $value The `sec` value to set
- */
- public function setSec($value)
- {
- $this->fixedTime['sec'] = $value;
- }
-
- /**
- * Returns a timestamp array
- *
- * @return int[] Array containing `sec` and `usec` components of a timestamp
- */
- public function currentTime()
- {
- return $this->fixedTime;
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider\Time;
-
-use Ramsey\Uuid\Provider\TimeProviderInterface;
-
-/**
- * SystemTimeProvider uses built-in PHP functions to provide the time
- */
-class SystemTimeProvider implements TimeProviderInterface
-{
- /**
- * Returns a timestamp array
- *
- * @return int[] Array containing `sec` and `usec` components of a timestamp
- */
- public function currentTime()
- {
- return gettimeofday();
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid\Provider;
-
-/**
- * TimeProviderInterface provides functionality to get the time from a specific
- * type of time provider
- */
-interface TimeProviderInterface
-{
- /**
- * Returns a timestamp array
- *
- * @return int[] Array guaranteed to contain `sec` and `usec` components of a timestamp
- */
- public function currentTime();
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid;
-
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\Exception\UnsupportedOperationException;
-
-/**
- * Represents a universally unique identifier (UUID), according to RFC 4122.
- *
- * This class provides immutable UUID objects (the Uuid class) and the static
- * methods `uuid1()`, `uuid3()`, `uuid4()`, and `uuid5()` for generating version
- * 1, 3, 4, and 5 UUIDs as specified in RFC 4122.
- *
- * If all you want is a unique ID, you should probably call `uuid1()` or `uuid4()`.
- * Note that `uuid1()` may compromise privacy since it creates a UUID containing
- * the computer’s network address. `uuid4()` creates a random UUID.
- *
- * @link http://tools.ietf.org/html/rfc4122
- * @link http://en.wikipedia.org/wiki/Universally_unique_identifier
- * @link http://docs.python.org/3/library/uuid.html
- * @link http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html
- */
-class Uuid implements UuidInterface
-{
- /**
- * When this namespace is specified, the name string is a fully-qualified domain name.
- * @link http://tools.ietf.org/html/rfc4122#appendix-C
- */
- const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
-
- /**
- * When this namespace is specified, the name string is a URL.
- * @link http://tools.ietf.org/html/rfc4122#appendix-C
- */
- const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
-
- /**
- * When this namespace is specified, the name string is an ISO OID.
- * @link http://tools.ietf.org/html/rfc4122#appendix-C
- */
- const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
-
- /**
- * When this namespace is specified, the name string is an X.500 DN in DER or a text output format.
- * @link http://tools.ietf.org/html/rfc4122#appendix-C
- */
- const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
-
- /**
- * The nil UUID is special form of UUID that is specified to have all 128 bits set to zero.
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.7
- */
- const NIL = '00000000-0000-0000-0000-000000000000';
-
- /**
- * Reserved for NCS compatibility.
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1
- */
- const RESERVED_NCS = 0;
-
- /**
- * Specifies the UUID layout given in RFC 4122.
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1
- */
- const RFC_4122 = 2;
-
- /**
- * Reserved for Microsoft compatibility.
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1
- */
- const RESERVED_MICROSOFT = 6;
-
- /**
- * Reserved for future definition.
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1
- */
- const RESERVED_FUTURE = 7;
-
- /**
- * Regular expression pattern for matching a valid UUID of any variant.
- */
- const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$';
-
- /**
- * Version 1 (time-based) UUID object constant identifier
- */
- const UUID_TYPE_TIME = 1;
-
- /**
- * Version 2 (identifier-based) UUID object constant identifier
- */
- const UUID_TYPE_IDENTIFIER = 2;
-
- /**
- * Version 3 (name-based and hashed with MD5) UUID object constant identifier
- */
- const UUID_TYPE_HASH_MD5 = 3;
-
- /**
- * Version 4 (random) UUID object constant identifier
- */
- const UUID_TYPE_RANDOM = 4;
-
- /**
- * Version 5 (name-based and hashed with SHA1) UUID object constant identifier
- */
- const UUID_TYPE_HASH_SHA1 = 5;
-
- /**
- * The factory to use when creating UUIDs.
- * @var UuidFactoryInterface
- */
- private static $factory = null;
-
- /**
- * The codec to use when encoding or decoding UUID strings.
- * @var CodecInterface
- */
- protected $codec;
-
- /**
- * The fields that make up this UUID.
- *
- * This is initialized to the nil value.
- *
- * @var array
- * @see UuidInterface::getFieldsHex()
- */
- protected $fields = array(
- 'time_low' => '00000000',
- 'time_mid' => '0000',
- 'time_hi_and_version' => '0000',
- 'clock_seq_hi_and_reserved' => '00',
- 'clock_seq_low' => '00',
- 'node' => '000000000000',
- );
-
- /**
- * The number converter to use for converting hex values to/from integers.
- * @var NumberConverterInterface
- */
- protected $converter;
-
- /**
- * Creates a universally unique identifier (UUID) from an array of fields.
- *
- * Unless you're making advanced use of this library to generate identifiers
- * that deviate from RFC 4122, you probably do not want to instantiate a
- * UUID directly. Use the static methods, instead:
- *
- * ```
- * use Ramsey\Uuid\Uuid;
- *
- * $timeBasedUuid = Uuid::uuid1();
- * $namespaceMd5Uuid = Uuid::uuid3(Uuid::NAMESPACE_URL, 'http://php.net/');
- * $randomUuid = Uuid::uuid4();
- * $namespaceSha1Uuid = Uuid::uuid5(Uuid::NAMESPACE_URL, 'http://php.net/');
- * ```
- *
- * @param array $fields An array of fields from which to construct a UUID;
- * see {@see \Ramsey\Uuid\UuidInterface::getFieldsHex()} for array structure.
- * @param NumberConverterInterface $converter The number converter to use
- * for converting hex values to/from integers.
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings.
- */
- public function __construct(
- array $fields,
- NumberConverterInterface $converter,
- CodecInterface $codec
- ) {
- $this->fields = $fields;
- $this->codec = $codec;
- $this->converter = $converter;
- }
-
- /**
- * Converts this UUID object to a string when the object is used in any
- * string context.
- *
- * @return string
- * @link http://www.php.net/manual/en/language.oop5.magic.php#object.tostring
- */
- public function __toString()
- {
- return $this->toString();
- }
-
- /**
- * Converts this UUID object to a string when the object is serialized
- * with `json_encode()`
- *
- * @return string
- * @link http://php.net/manual/en/class.jsonserializable.php
- */
- public function jsonSerialize()
- {
- return $this->toString();
- }
-
- /**
- * Converts this UUID object to a string when the object is serialized
- * with `serialize()`
- *
- * @return string
- * @link http://php.net/manual/en/class.serializable.php
- */
- public function serialize()
- {
- return $this->toString();
- }
-
- /**
- * Re-constructs the object from its serialized form.
- *
- * @param string $serialized
- * @link http://php.net/manual/en/class.serializable.php
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function unserialize($serialized)
- {
- $uuid = self::fromString($serialized);
- $this->codec = $uuid->codec;
- $this->converter = $uuid->converter;
- $this->fields = $uuid->fields;
- }
-
- public function compareTo(UuidInterface $other)
- {
- $comparison = 0;
-
- if ($this->getMostSignificantBitsHex() < $other->getMostSignificantBitsHex()) {
- $comparison = -1;
- } elseif ($this->getMostSignificantBitsHex() > $other->getMostSignificantBitsHex()) {
- $comparison = 1;
- } elseif ($this->getLeastSignificantBitsHex() < $other->getLeastSignificantBitsHex()) {
- $comparison = -1;
- } elseif ($this->getLeastSignificantBitsHex() > $other->getLeastSignificantBitsHex()) {
- $comparison = 1;
- }
-
- return $comparison;
- }
-
- public function equals($other)
- {
- if (!($other instanceof UuidInterface)) {
- return false;
- }
-
- return ($this->compareTo($other) == 0);
- }
-
- public function getBytes()
- {
- return $this->codec->encodeBinary($this);
- }
-
- /**
- * Returns the high field of the clock sequence multiplexed with the variant
- * (bits 65-72 of the UUID).
- *
- * @return int Unsigned 8-bit integer value of clock_seq_hi_and_reserved
- */
- public function getClockSeqHiAndReserved()
- {
- return hexdec($this->getClockSeqHiAndReservedHex());
- }
-
- public function getClockSeqHiAndReservedHex()
- {
- return $this->fields['clock_seq_hi_and_reserved'];
- }
-
- /**
- * Returns the low field of the clock sequence (bits 73-80 of the UUID).
- *
- * @return int Unsigned 8-bit integer value of clock_seq_low
- */
- public function getClockSeqLow()
- {
- return hexdec($this->getClockSeqLowHex());
- }
-
- public function getClockSeqLowHex()
- {
- return $this->fields['clock_seq_low'];
- }
-
- /**
- * Returns the clock sequence value associated with this UUID.
- *
- * For UUID version 1, the clock sequence is used to help avoid
- * duplicates that could arise when the clock is set backwards in time
- * or if the node ID changes.
- *
- * For UUID version 3 or 5, the clock sequence is a 14-bit value
- * constructed from a name as described in RFC 4122, Section 4.3.
- *
- * For UUID version 4, clock sequence is a randomly or pseudo-randomly
- * generated 14-bit value as described in RFC 4122, Section 4.4.
- *
- * @return int Unsigned 14-bit integer value of clock sequence
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.5
- */
- public function getClockSequence()
- {
- return (($this->getClockSeqHiAndReserved() & 0x3f) << 8)
- | $this->getClockSeqLow();
- }
-
- public function getClockSequenceHex()
- {
- return sprintf('%04x', $this->getClockSequence());
- }
-
- public function getNumberConverter()
- {
- return $this->converter;
- }
-
- /**
- * @inheritdoc
- */
- public function getDateTime()
- {
- if ($this->getVersion() != 1) {
- throw new UnsupportedOperationException('Not a time-based UUID');
- }
-
- $unixTime = ($this->getTimestamp() - 0x01b21dd213814000) / 1e7;
- $unixTime = number_format($unixTime, 0, '', '');
-
- return new \DateTime("@{$unixTime}");
- }
-
- /**
- * Returns an array of the fields of this UUID, with keys named according
- * to the RFC 4122 names for the fields.
- *
- * * **time_low**: The low field of the timestamp, an unsigned 32-bit integer
- * * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer
- * * **time_hi_and_version**: The high field of the timestamp multiplexed with
- * the version number, an unsigned 16-bit integer
- * * **clock_seq_hi_and_reserved**: The high field of the clock sequence
- * multiplexed with the variant, an unsigned 8-bit integer
- * * **clock_seq_low**: The low field of the clock sequence, an unsigned
- * 8-bit integer
- * * **node**: The spatially unique node identifier, an unsigned 48-bit
- * integer
- *
- * @return array The UUID fields represented as integer values
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.2
- */
- public function getFields()
- {
- return array(
- 'time_low' => $this->getTimeLow(),
- 'time_mid' => $this->getTimeMid(),
- 'time_hi_and_version' => $this->getTimeHiAndVersion(),
- 'clock_seq_hi_and_reserved' => $this->getClockSeqHiAndReserved(),
- 'clock_seq_low' => $this->getClockSeqLow(),
- 'node' => $this->getNode(),
- );
- }
-
- public function getFieldsHex()
- {
- return $this->fields;
- }
-
- public function getHex()
- {
- return str_replace('-', '', $this->toString());
- }
-
- /**
- * @inheritdoc
- */
- public function getInteger()
- {
- return $this->converter->fromHex($this->getHex());
- }
-
- /**
- * Returns the least significant 64 bits of this UUID's 128 bit value.
- *
- * @return mixed Converted representation of the unsigned 64-bit integer value
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- */
- public function getLeastSignificantBits()
- {
- return $this->converter->fromHex($this->getLeastSignificantBitsHex());
- }
-
- public function getLeastSignificantBitsHex()
- {
- return sprintf(
- '%02s%02s%012s',
- $this->fields['clock_seq_hi_and_reserved'],
- $this->fields['clock_seq_low'],
- $this->fields['node']
- );
- }
-
- /**
- * Returns the most significant 64 bits of this UUID's 128 bit value.
- *
- * @return mixed Converted representation of the unsigned 64-bit integer value
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- */
- public function getMostSignificantBits()
- {
- return $this->converter->fromHex($this->getMostSignificantBitsHex());
- }
-
- public function getMostSignificantBitsHex()
- {
- return sprintf(
- '%08s%04s%04s',
- $this->fields['time_low'],
- $this->fields['time_mid'],
- $this->fields['time_hi_and_version']
- );
- }
-
- /**
- * Returns the node value associated with this UUID
- *
- * For UUID version 1, the node field consists of an IEEE 802 MAC
- * address, usually the host address. For systems with multiple IEEE
- * 802 addresses, any available one can be used. The lowest addressed
- * octet (octet number 10) contains the global/local bit and the
- * unicast/multicast bit, and is the first octet of the address
- * transmitted on an 802.3 LAN.
- *
- * For systems with no IEEE address, a randomly or pseudo-randomly
- * generated value may be used; see RFC 4122, Section 4.5. The
- * multicast bit must be set in such addresses, in order that they
- * will never conflict with addresses obtained from network cards.
- *
- * For UUID version 3 or 5, the node field is a 48-bit value constructed
- * from a name as described in RFC 4122, Section 4.3.
- *
- * For UUID version 4, the node field is a randomly or pseudo-randomly
- * generated 48-bit value as described in RFC 4122, Section 4.4.
- *
- * @return int Unsigned 48-bit integer value of node
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.6
- */
- public function getNode()
- {
- return hexdec($this->getNodeHex());
- }
-
- public function getNodeHex()
- {
- return $this->fields['node'];
- }
-
- /**
- * Returns the high field of the timestamp multiplexed with the version
- * number (bits 49-64 of the UUID).
- *
- * @return int Unsigned 16-bit integer value of time_hi_and_version
- */
- public function getTimeHiAndVersion()
- {
- return hexdec($this->getTimeHiAndVersionHex());
- }
-
- public function getTimeHiAndVersionHex()
- {
- return $this->fields['time_hi_and_version'];
- }
-
- /**
- * Returns the low field of the timestamp (the first 32 bits of the UUID).
- *
- * @return int Unsigned 32-bit integer value of time_low
- */
- public function getTimeLow()
- {
- return hexdec($this->getTimeLowHex());
- }
-
- public function getTimeLowHex()
- {
- return $this->fields['time_low'];
- }
-
- /**
- * Returns the middle field of the timestamp (bits 33-48 of the UUID).
- *
- * @return int Unsigned 16-bit integer value of time_mid
- */
- public function getTimeMid()
- {
- return hexdec($this->getTimeMidHex());
- }
-
- public function getTimeMidHex()
- {
- return $this->fields['time_mid'];
- }
-
- /**
- * Returns the timestamp value associated with this UUID.
- *
- * The 60 bit timestamp value is constructed from the time_low,
- * time_mid, and time_hi fields of this UUID. The resulting
- * timestamp is measured in 100-nanosecond units since midnight,
- * October 15, 1582 UTC.
- *
- * The timestamp value is only meaningful in a time-based UUID, which
- * has version type 1. If this UUID is not a time-based UUID then
- * this method throws UnsupportedOperationException.
- *
- * @return int Unsigned 60-bit integer value of the timestamp
- * @throws UnsupportedOperationException If this UUID is not a version 1 UUID
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.4
- */
- public function getTimestamp()
- {
- if ($this->getVersion() != 1) {
- throw new UnsupportedOperationException('Not a time-based UUID');
- }
-
- return hexdec($this->getTimestampHex());
- }
-
- /**
- * @inheritdoc
- */
- public function getTimestampHex()
- {
- if ($this->getVersion() != 1) {
- throw new UnsupportedOperationException('Not a time-based UUID');
- }
-
- return sprintf(
- '%03x%04s%08s',
- ($this->getTimeHiAndVersion() & 0x0fff),
- $this->fields['time_mid'],
- $this->fields['time_low']
- );
- }
-
- public function getUrn()
- {
- return 'urn:uuid:' . $this->toString();
- }
-
- public function getVariant()
- {
- $clockSeq = $this->getClockSeqHiAndReserved();
- if (0 === ($clockSeq & 0x80)) {
- $variant = self::RESERVED_NCS;
- } elseif (0 === ($clockSeq & 0x40)) {
- $variant = self::RFC_4122;
- } elseif (0 === ($clockSeq & 0x20)) {
- $variant = self::RESERVED_MICROSOFT;
- } else {
- $variant = self::RESERVED_FUTURE;
- }
-
- return $variant;
- }
-
- public function getVersion()
- {
- if ($this->getVariant() == self::RFC_4122) {
- return (int) (($this->getTimeHiAndVersion() >> 12) & 0x0f);
- }
-
- return null;
- }
-
- public function toString()
- {
- return $this->codec->encode($this);
- }
-
- /**
- * Returns the currently set factory used to create UUIDs.
- *
- * @return UuidFactoryInterface
- */
- public static function getFactory()
- {
- if (!self::$factory) {
- self::$factory = new UuidFactory();
- }
-
- return self::$factory;
- }
-
- /**
- * Sets the factory used to create UUIDs.
- *
- * @param UuidFactoryInterface $factory
- */
- public static function setFactory(UuidFactoryInterface $factory)
- {
- self::$factory = $factory;
- }
-
- /**
- * Creates a UUID from a byte string.
- *
- * @param string $bytes
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- * @throws \InvalidArgumentException
- */
- public static function fromBytes($bytes)
- {
- return self::getFactory()->fromBytes($bytes);
- }
-
- /**
- * Creates a UUID from the string standard representation.
- *
- * @param string $name A string that specifies a UUID
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public static function fromString($name)
- {
- return self::getFactory()->fromString($name);
- }
-
- /**
- * Creates a UUID from a 128-bit integer string.
- *
- * @param string $integer String representation of 128-bit integer
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public static function fromInteger($integer)
- {
- return self::getFactory()->fromInteger($integer);
- }
-
- /**
- * Check if a string is a valid UUID.
- *
- * @param string $uuid The string UUID to test
- * @return boolean
- */
- public static function isValid($uuid)
- {
- $uuid = str_replace(array('urn:', 'uuid:', '{', '}'), '', $uuid);
-
- if ($uuid == self::NIL) {
- return true;
- }
-
- if (!preg_match('/' . self::VALID_PATTERN . '/D', $uuid)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Generate a version 1 UUID from a host ID, sequence number, and the current time.
- *
- * @param int|string $node A 48-bit number representing the hardware address
- * This number may be represented as an integer or a hexadecimal string.
- * @param int $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes.
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if called on a 32-bit system and
- * `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public static function uuid1($node = null, $clockSeq = null)
- {
- return self::getFactory()->uuid1($node, $clockSeq);
- }
-
- /**
- * Generate a version 3 UUID based on the MD5 hash of a namespace identifier
- * (which is a UUID) and a name (which is a string).
- *
- * @param string $ns The UUID namespace in which to create the named UUID
- * @param string $name The name to create a UUID for
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public static function uuid3($ns, $name)
- {
- return self::getFactory()->uuid3($ns, $name);
- }
-
- /**
- * Generate a version 4 (random) UUID.
- *
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception
- */
- public static function uuid4()
- {
- return self::getFactory()->uuid4();
- }
-
- /**
- * Generate a version 5 UUID based on the SHA-1 hash of a namespace
- * identifier (which is a UUID) and a name (which is a string).
- *
- * @param string $ns The UUID namespace in which to create the named UUID
- * @param string $name The name to create a UUID for
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public static function uuid5($ns, $name)
- {
- return self::getFactory()->uuid5($ns, $name);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid;
-
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Provider\NodeProviderInterface;
-use Ramsey\Uuid\Generator\RandomGeneratorInterface;
-use Ramsey\Uuid\Generator\TimeGeneratorInterface;
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\Builder\UuidBuilderInterface;
-
-class UuidFactory implements UuidFactoryInterface
-{
- /**
- * @var CodecInterface
- */
- private $codec = null;
-
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider = null;
-
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter = null;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator = null;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator = null;
-
- /**
- * @var UuidBuilderInterface
- */
- private $uuidBuilder = null;
-
- /**
- * Constructs a `UuidFactory` for creating `Ramsey\Uuid\UuidInterface` instances
- *
- * @param FeatureSet $features A set of features for use when creating UUIDs
- */
- public function __construct(FeatureSet $features = null)
- {
- $features = $features ?: new FeatureSet();
-
- $this->codec = $features->getCodec();
- $this->nodeProvider = $features->getNodeProvider();
- $this->numberConverter = $features->getNumberConverter();
- $this->randomGenerator = $features->getRandomGenerator();
- $this->timeGenerator = $features->getTimeGenerator();
- $this->uuidBuilder = $features->getBuilder();
- }
-
- /**
- * Returns the UUID coder-decoder used by this factory
- *
- * @return CodecInterface
- */
- public function getCodec()
- {
- return $this->codec;
- }
-
- /**
- * Sets the UUID coder-decoder used by this factory
- *
- * @param CodecInterface $codec
- */
- public function setCodec(CodecInterface $codec)
- {
- $this->codec = $codec;
- }
-
- /**
- * Returns the system node ID provider used by this factory
- *
- * @return NodeProviderInterface
- */
- public function getNodeProvider()
- {
- return $this->nodeProvider;
- }
-
- /**
- * Returns the random UUID generator used by this factory
- *
- * @return RandomGeneratorInterface
- */
- public function getRandomGenerator()
- {
- return $this->randomGenerator;
- }
-
- /**
- * Returns the time-based UUID generator used by this factory
- *
- * @return TimeGeneratorInterface
- */
- public function getTimeGenerator()
- {
- return $this->timeGenerator;
- }
-
- /**
- * Sets the time-based UUID generator this factory will use to generate version 1 UUIDs
- *
- * @param TimeGeneratorInterface $generator
- */
- public function setTimeGenerator(TimeGeneratorInterface $generator)
- {
- $this->timeGenerator = $generator;
- }
-
- /**
- * Returns the number converter used by this factory
- *
- * @return NumberConverterInterface
- */
- public function getNumberConverter()
- {
- return $this->numberConverter;
- }
-
- /**
- * Sets the random UUID generator this factory will use to generate version 4 UUIDs
- *
- * @param RandomGeneratorInterface $generator
- */
- public function setRandomGenerator(RandomGeneratorInterface $generator)
- {
- $this->randomGenerator = $generator;
- }
-
- /**
- * Sets the number converter this factory will use
- *
- * @param NumberConverterInterface $converter
- */
- public function setNumberConverter(NumberConverterInterface $converter)
- {
- $this->numberConverter = $converter;
- }
-
- /**
- * Returns the UUID builder this factory uses when creating `Uuid` instances
- *
- * @return UuidBuilderInterface $builder
- */
- public function getUuidBuilder()
- {
- return $this->uuidBuilder;
- }
-
- /**
- * Sets the UUID builder this factory will use when creating `Uuid` instances
- *
- * @param UuidBuilderInterface $builder
- */
- public function setUuidBuilder(UuidBuilderInterface $builder)
- {
- $this->uuidBuilder = $builder;
- }
-
- /**
- * @inheritdoc
- */
- public function fromBytes($bytes)
- {
- return $this->codec->decodeBytes($bytes);
- }
-
- /**
- * @inheritdoc
- */
- public function fromString($uuid)
- {
- $uuid = strtolower($uuid);
- return $this->codec->decode($uuid);
- }
-
- /**
- * @inheritdoc
- */
- public function fromInteger($integer)
- {
- $hex = $this->numberConverter->toHex($integer);
- $hex = str_pad($hex, 32, '0', STR_PAD_LEFT);
-
- return $this->fromString($hex);
- }
-
- /**
- * @inheritdoc
- */
- public function uuid1($node = null, $clockSeq = null)
- {
- $bytes = $this->timeGenerator->generate($node, $clockSeq);
- $hex = bin2hex($bytes);
-
- return $this->uuidFromHashedName($hex, 1);
- }
-
- /**
- * @inheritdoc
- */
- public function uuid3($ns, $name)
- {
- return $this->uuidFromNsAndName($ns, $name, 3, 'md5');
- }
-
- /**
- * @inheritdoc
- */
- public function uuid4()
- {
- $bytes = $this->randomGenerator->generate(16);
-
- // When converting the bytes to hex, it turns into a 32-character
- // hexadecimal string that looks a lot like an MD5 hash, so at this
- // point, we can just pass it to uuidFromHashedName.
- $hex = bin2hex($bytes);
-
- return $this->uuidFromHashedName($hex, 4);
- }
-
- /**
- * @inheritdoc
- */
- public function uuid5($ns, $name)
- {
- return $this->uuidFromNsAndName($ns, $name, 5, 'sha1');
- }
-
- /**
- * Returns a `Uuid`
- *
- * Uses the configured builder and codec and the provided array of hexadecimal
- * value UUID fields to construct a `Uuid` object.
- *
- * @param array $fields An array of fields from which to construct a UUID;
- * see {@see \Ramsey\Uuid\UuidInterface::getFieldsHex()} for array structure.
- * @return UuidInterface
- */
- public function uuid(array $fields)
- {
- return $this->uuidBuilder->build($this->codec, $fields);
- }
-
- /**
- * Returns a version 3 or 5 namespaced `Uuid`
- *
- * @param string|UuidInterface $ns The UUID namespace to use
- * @param string $name The string to hash together with the namespace
- * @param int $version The version of UUID to create (3 or 5)
- * @param string $hashFunction The hash function to use when hashing together
- * the namespace and name
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- protected function uuidFromNsAndName($ns, $name, $version, $hashFunction)
- {
- if (!($ns instanceof UuidInterface)) {
- $ns = $this->codec->decode($ns);
- }
-
- $hash = call_user_func($hashFunction, ($ns->getBytes() . $name));
-
- return $this->uuidFromHashedName($hash, $version);
- }
-
- /**
- * Returns a `Uuid` created from `$hash` with the version field set to `$version`
- * and the variant field set for RFC 4122
- *
- * @param string $hash The hash to use when creating the UUID
- * @param int $version The UUID version to set for this hash (1, 3, 4, or 5)
- * @return UuidInterface
- */
- protected function uuidFromHashedName($hash, $version)
- {
- $timeHi = BinaryUtils::applyVersion(substr($hash, 12, 4), $version);
- $clockSeqHi = BinaryUtils::applyVariant(hexdec(substr($hash, 16, 2)));
-
- $fields = array(
- 'time_low' => substr($hash, 0, 8),
- 'time_mid' => substr($hash, 8, 4),
- 'time_hi_and_version' => str_pad(dechex($timeHi), 4, '0', STR_PAD_LEFT),
- 'clock_seq_hi_and_reserved' => str_pad(dechex($clockSeqHi), 2, '0', STR_PAD_LEFT),
- 'clock_seq_low' => substr($hash, 18, 2),
- 'node' => substr($hash, 20, 12),
- );
-
- return $this->uuid($fields);
- }
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid;
-
-/**
- * UuidFactoryInterface defines common functionality all `UuidFactory` instances
- * must implement
- */
-interface UuidFactoryInterface
-{
- /**
- * Generate a version 1 UUID from a host ID, sequence number, and the current time.
- *
- * @param int|string|null $node A 48-bit number representing the hardware address
- * This number may be represented as an integer or a hexadecimal string.
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates that
- * could arise when the clock is set backwards in time or if the node ID
- * changes.
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if called on a 32-bit system and
- * `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception if it was not possible to gather sufficient entropy
- */
- public function uuid1($node = null, $clockSeq = null);
-
- /**
- * Generate a version 3 UUID based on the MD5 hash of a namespace identifier
- * (which is a UUID) and a name (which is a string).
- *
- * @param string $ns The UUID namespace in which to create the named UUID
- * @param string $name The name to create a UUID for
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function uuid3($ns, $name);
-
- /**
- * Generate a version 4 (random) UUID.
- *
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- * @throws \InvalidArgumentException
- * @throws \Exception
- */
- public function uuid4();
-
- /**
- * Generate a version 5 UUID based on the SHA-1 hash of a namespace
- * identifier (which is a UUID) and a name (which is a string).
- *
- * @param string $ns The UUID namespace in which to create the named UUID
- * @param string $name The name to create a UUID for
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function uuid5($ns, $name);
-
- /**
- * Creates a UUID from a byte string.
- *
- * @param string $bytes A 16-byte string representation of a UUID
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- * @throws \InvalidArgumentException if string has not 16 characters
- */
- public function fromBytes($bytes);
-
- /**
- * Creates a UUID from the string standard representation
- *
- * @param string $uuid A string representation of a UUID
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function fromString($uuid);
-
- /**
- * Creates a `Uuid` from an integer representation
- *
- * The integer representation may be a real integer, a string integer, or
- * an integer representation supported by a configured number converter.
- *
- * @param mixed $integer The integer to use when creating a `Uuid` from an
- * integer; may be of any type understood by the configured number converter
- * @return UuidInterface
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- * @throws \Ramsey\Uuid\Exception\InvalidUuidStringException
- */
- public function fromInteger($integer);
-}
+++ /dev/null
-<?php
-/**
- * This file is part of the ramsey/uuid library
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- *
- * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
- * @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
- */
-
-namespace Ramsey\Uuid;
-
-use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Exception\UnsupportedOperationException;
-
-/**
- * UuidInterface defines common functionality for all universally unique
- * identifiers (UUIDs)
- */
-interface UuidInterface extends \JsonSerializable, \Serializable
-{
- /**
- * Compares this UUID to the specified UUID.
- *
- * The first of two UUIDs is greater than the second if the most
- * significant field in which the UUIDs differ is greater for the first
- * UUID.
- *
- * * Q. What's the value of being able to sort UUIDs?
- * * A. Use them as keys in a B-Tree or similar mapping.
- *
- * @param UuidInterface $other UUID to which this UUID is compared
- * @return int -1, 0 or 1 as this UUID is less than, equal to, or greater than `$uuid`
- */
- public function compareTo(UuidInterface $other);
-
- /**
- * Compares this object to the specified object.
- *
- * The result is true if and only if the argument is not null, is a UUID
- * object, has the same variant, and contains the same value, bit for bit,
- * as this UUID.
- *
- * @param object $other
- * @return bool True if `$other` is equal to this UUID
- */
- public function equals($other);
-
- /**
- * Returns the UUID as a 16-byte string (containing the six integer fields
- * in big-endian byte order).
- *
- * @return string
- */
- public function getBytes();
-
- /**
- * Returns the number converter to use for converting hex values to/from integers.
- *
- * @return NumberConverterInterface
- */
- public function getNumberConverter();
-
- /**
- * Returns the hexadecimal value of the UUID.
- *
- * @return string
- */
- public function getHex();
-
- /**
- * Returns an array of the fields of this UUID, with keys named according
- * to the RFC 4122 names for the fields.
- *
- * * **time_low**: The low field of the timestamp, an unsigned 32-bit integer
- * * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer
- * * **time_hi_and_version**: The high field of the timestamp multiplexed with
- * the version number, an unsigned 16-bit integer
- * * **clock_seq_hi_and_reserved**: The high field of the clock sequence
- * multiplexed with the variant, an unsigned 8-bit integer
- * * **clock_seq_low**: The low field of the clock sequence, an unsigned
- * 8-bit integer
- * * **node**: The spatially unique node identifier, an unsigned 48-bit
- * integer
- *
- * @return array The UUID fields represented as hexadecimal values
- */
- public function getFieldsHex();
-
- /**
- * Returns the high field of the clock sequence multiplexed with the variant
- * (bits 65-72 of the UUID).
- *
- * @return string Hexadecimal value of clock_seq_hi_and_reserved
- */
- public function getClockSeqHiAndReservedHex();
-
- /**
- * Returns the low field of the clock sequence (bits 73-80 of the UUID).
- *
- * @return string Hexadecimal value of clock_seq_low
- */
- public function getClockSeqLowHex();
-
- /**
- * Returns the clock sequence value associated with this UUID.
- *
- * @return string Hexadecimal value of clock sequence
- */
- public function getClockSequenceHex();
-
- /**
- * Returns a PHP `DateTime` object representing the timestamp associated
- * with this UUID.
- *
- * The timestamp value is only meaningful in a time-based UUID, which
- * has version type 1. If this UUID is not a time-based UUID then
- * this method throws `UnsupportedOperationException`.
- *
- * @return \DateTime A PHP DateTime representation of the date
- * @throws UnsupportedOperationException If this UUID is not a version 1 UUID
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if called in a 32-bit system and
- * `Moontoast\Math\BigNumber` is not present
- */
- public function getDateTime();
-
- /**
- * Returns the integer value of the UUID, converted to an appropriate number
- * representation.
- *
- * @return mixed Converted representation of the unsigned 128-bit integer value
- * @throws \Ramsey\Uuid\Exception\UnsatisfiedDependencyException if `Moontoast\Math\BigNumber` is not present
- */
- public function getInteger();
-
- /**
- * Returns the least significant 64 bits of this UUID's 128 bit value.
- *
- * @return string Hexadecimal value of least significant bits
- */
- public function getLeastSignificantBitsHex();
-
- /**
- * Returns the most significant 64 bits of this UUID's 128 bit value.
- *
- * @return string Hexadecimal value of most significant bits
- */
- public function getMostSignificantBitsHex();
-
- /**
- * Returns the node value associated with this UUID
- *
- * For UUID version 1, the node field consists of an IEEE 802 MAC
- * address, usually the host address. For systems with multiple IEEE
- * 802 addresses, any available one can be used. The lowest addressed
- * octet (octet number 10) contains the global/local bit and the
- * unicast/multicast bit, and is the first octet of the address
- * transmitted on an 802.3 LAN.
- *
- * For systems with no IEEE address, a randomly or pseudo-randomly
- * generated value may be used; see RFC 4122, Section 4.5. The
- * multicast bit must be set in such addresses, in order that they
- * will never conflict with addresses obtained from network cards.
- *
- * For UUID version 3 or 5, the node field is a 48-bit value constructed
- * from a name as described in RFC 4122, Section 4.3.
- *
- * For UUID version 4, the node field is a randomly or pseudo-randomly
- * generated 48-bit value as described in RFC 4122, Section 4.4.
- *
- * @return string Hexadecimal value of node
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.6
- */
- public function getNodeHex();
-
- /**
- * Returns the high field of the timestamp multiplexed with the version
- * number (bits 49-64 of the UUID).
- *
- * @return string Hexadecimal value of time_hi_and_version
- */
- public function getTimeHiAndVersionHex();
-
- /**
- * Returns the low field of the timestamp (the first 32 bits of the UUID).
- *
- * @return string Hexadecimal value of time_low
- */
- public function getTimeLowHex();
-
- /**
- * Returns the middle field of the timestamp (bits 33-48 of the UUID).
- *
- * @return string Hexadecimal value of time_mid
- */
- public function getTimeMidHex();
-
- /**
- * Returns the timestamp value associated with this UUID.
- *
- * The 60 bit timestamp value is constructed from the time_low,
- * time_mid, and time_hi fields of this UUID. The resulting
- * timestamp is measured in 100-nanosecond units since midnight,
- * October 15, 1582 UTC.
- *
- * The timestamp value is only meaningful in a time-based UUID, which
- * has version type 1. If this UUID is not a time-based UUID then
- * this method throws UnsupportedOperationException.
- *
- * @return string Hexadecimal value of the timestamp
- * @throws UnsupportedOperationException If this UUID is not a version 1 UUID
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.4
- */
- public function getTimestampHex();
-
- /**
- * Returns the string representation of the UUID as a URN.
- *
- * @return string
- * @link http://en.wikipedia.org/wiki/Uniform_Resource_Name
- */
- public function getUrn();
-
- /**
- * Returns the variant number associated with this UUID.
- *
- * The variant number describes the layout of the UUID. The variant
- * number has the following meaning:
- *
- * * 0 - Reserved for NCS backward compatibility
- * * 2 - The RFC 4122 variant (used by this class)
- * * 6 - Reserved, Microsoft Corporation backward compatibility
- * * 7 - Reserved for future definition
- *
- * @return int
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1
- */
- public function getVariant();
-
- /**
- * Returns the version number associated with this UUID.
- *
- * The version number describes how this UUID was generated and has the
- * following meaning:
- *
- * * 1 - Time-based UUID
- * * 2 - DCE security UUID
- * * 3 - Name-based UUID hashed with MD5
- * * 4 - Randomly generated UUID
- * * 5 - Name-based UUID hashed with SHA-1
- *
- * Returns null if this UUID is not an RFC 4122 variant, since version
- * is only meaningful for this variant.
- *
- * @return int|null
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.3
- */
- public function getVersion();
-
- /**
- * Converts this UUID into a string representation.
- *
- * @return string
- */
- public function toString();
-}
--- /dev/null
+travisci/ export-ignore
+tests/ export-ignore
--- /dev/null
+nbproject
+composer.lock
+composer.phar
+vendor
+/.idea
+/.project
+/travisci/tmp
+stomp-php.iml
\ No newline at end of file
--- /dev/null
+language: php
+
+sudo: true
+
+services:
+ - docker
+
+jobs:
+ include:
+ - &TEST
+ php: "5.6"
+ before_script:
+ - ./travisci/bin/start.sh
+ - composer install
+ - ./travisci/bin/logs.sh
+
+ script: vendor/bin/phpunit --debug
+
+ after_script:
+ - ./travisci/bin/stop.sh
+ - <<: *TEST
+ php: "7.0"
+ - <<: *TEST
+ php: "7.1"
+ - <<: *TEST
+ php: "7.2"
+ - <<: *TEST
+ php: "7.3"
+
+ - stage: Static analysis with phpstan
+ php: "7.3"
+ script:
+ - composer require --dev phpstan/phpstan
+ - vendor/bin/phpstan analyse
\ No newline at end of file
--- /dev/null
+Changelog stomp-php
+-------------------
+
+4.0.0 (Full Stomp 1.1 / 1.2 Support)
+------------------------------------
+
+- Updated functional testsuite for different brokers (amq,aplo,rabbit), update travis-ci.
+- Update Parser in order to be compliant with stomp-1.2 (https://stomp.github.io/stomp-specification-1.2.html)
+- ACK Mode is now `auto` by default.
+- Implement StateMachine Pattern `StatefulStomp`.
+- Restructure project, new Namespaces `Protocol`, `Transport`, `Network`.
+- Make Client much smaller, remove all non low level methods to `SimpleStomp`.
+- Testsuite rework...
+- Move examples to https://github.com/stomp-php/stomp-php-examples.
+- add utils for `ActiveMq` durable subscription and `Apollo` queue browser.
+
+4.0.1
+-----
+- do not throw read exception if the next byte after a complete read is a zero byte. (https://github.com/stomp-php/stomp-php/issues/39)
+- allow to reset the parser internal state and buffer. (https://github.com/stomp-php/stomp-php/issues/40)
+
+4.1.0
+-----
+- fixed header escaping in legacy mode in Parser (28ed8b6)
+- when the Parser is working in legacyMode it should produce Frames working in legacyMode (d257b98)
+- validate given ack SUBSCRIBE frame values against the STOMP spec (8043970)
+- Added a OpenMq Broker (0638958)
+- updated AMQ ci test version from 5.13.0 to 5.13.3 (ee37df6)
+- updated RMQ ci test version from 3.5.6 to 3.6.2 (ee37df6)
+- updated durable tests for RMQ (pass 'auto-delete' header and replaced 'persistent' with 'durable' header) (ee37df6)
+- updated erlang from R14B04 to latest version (travis) (ee37df6)
+- increase read timeout for amq abort test (ee37df6)
+
+4.1.1
+-----
+- fixed Null-Byte handling, thanks to @andrewbelcher (https://github.com/stomp-php/stomp-php/issues/54)
+
+
+4.1.2
+-----
+- update nack and ack Frames according to stomp 1.1 specification, thanks to @rawkode (https://github.com/stomp-php/stomp-php/issues/56)
+
+4.1.3
+-----
+- persistent connection flag for socket, thanks to @tenerd (https://github.com/stomp-php/stomp-php/issues/57)
+
+4.1.4
+-----
+- add headers getter in Frame class, thanks to @surrealcristian (https://github.com/stomp-php/stomp-php/issues/61)
+
+4.1.5
+-----
+- fix for false exceptions in combination with pcntl_signal (https://github.com/stomp-php/stomp-php/pull/65)
+
+4.2.0
+-----
+- fix invalid class hierarchy for `Stomp\Transport\Map` changed parent from `Frame` to `Message`
+- add option to register own message type handlers in `Stomp\Transport\FrameFactory` (https://github.com/stomp-php/stomp-php/pull/64)
+
+4.2.1
+-----
+- Update Connector to support `_` in the broker uri, thanks to @campru (https://github.com/stomp-php/stomp-php/pull/66)
+
+4.2.2
+-----
+- add support for outgoing heartbeats and a basic heartbeat emitter, than can be added to the connection (see stomp-php-examples) thanks to @andrewbelcher and @staabm (https://github.com/stomp-php/stomp-php/pull/72, https://github.com/stomp-php/stomp-php/pull/60)
+
+4.3.0
+------
+- bug: Message incorrectly parsed when body contains \r\n\r\n but delimiter is \n\n thanks to @mattford (https://github.com/stomp-php/stomp-php/issues/93, https://github.com/stomp-php/stomp-php/issues/94)
+- bc: #87 drop php-5.5 support (if you still need to use php-5.5 we can provide a release 4.2.* release for #93 too, but ask for it)
+- #91, #90, #89, #88, #87, #86, #84, #83, #82, #81, #80, #78, #77, #76, #75, #74, #73 many code style improvements big thanks to @localheinz
+Thanks to @staabm for all the reviews :)
+
+4.3.1
+------
+- add requeue support on NACK for rabbitmq 4.3, thanks to @gm-ghanover (https://github.com/stomp-php/stomp-php/pull/102)
+
+4.4.0
+------
+- change to non blocking mode. Add writeTimeout see https://github.com/stomp-php/stomp-php/blob/master/src/Network/Connection.php#L219 defaults to 3 seconds (#104 @Shaa1 thanks for reporting, https://github.com/stomp-php/stomp-php/pull/107)
+- add git-export-ignore thanks to @staabm (https://github.com/stomp-php/stomp-php/pull/106)
+
+4.4.1
+------
+- fix parser fails on header values that contain \r (thanks to @riven8192 for the fix, https://github.com/stomp-php/stomp-php/pull/110)
+
+4.4.2
+------
+- fix client stuck at large messages (thanks to @ganeko for fix, https://github.com/stomp-php/stomp-php/pull/111)
+
+4.4.3
+------
+- add configuration for connection read/write may bytes (thanks to @ganeko for this enhancement, https://github.com/stomp-php/stomp-php/pull/113)
+
+4.5.0
+------
+- refined broken connection detection, not longer failing when `fread` returns empty string (thanks to @mlamm for reporting this, https://github.com/stomp-php/stomp-php/issues/115 and https://github.com/stomp-php/stomp-php/issues/114
+- Clients should now use either `ServerAliveObserver` or `HeartbeatEmitter` to verify the state of the connection, otherwise a broken connection might not be detected - especially when the socket is based on ssl.
+- stabilize client heartbeat implementation, added awareness for failing `Connection::sendAlive` calls, now causing `HeartbeatException`
+- added `ServerAliveObserver` in order to simplify detection of dead connections.
+- fixed connection read blocks on os signals until read timeout (thanks to @edefimov, https://github.com/stomp-php/stomp-php/issues/117)
\ No newline at end of file
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2005-2006 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+# Stomp PHP
+
+[](https://travis-ci.org/stomp-php/stomp-php)
+
+This project is a PHP [Stomp](http://stomp.github.com) Client that besides it implements the Stomp protocol fully,
+brings some ActiveMQ and Apollo specific utils that could make your messaging from PHP easier.
+
+## Credits
+
+This library was initially developed by [Dejan Bosanac](https://github.com/dejanb).
+We would like to thank you for your work and we're happy to continue it.
+
+## Version choice
+
+- For new projects you should use version `4.*` which requires `php-5.6`. Support for `php-5.6` ends with version `5.*`.
+- For projects running older php versions you can use version `4.2.*` for `php-5.5` and `3.*` for `php-5.3`, please consider to update php.
+- For running projects with `fusesource/stomp-php@2.x` clients you can use version `2.2.2`.
+- All version newer that `2.x` won't be compatible with `fusesource/stomp-php`. (https://github.com/dejanb/stomp-php.)
+
+## Installing
+
+```bash
+composer require stomp-php/stomp-php
+```
+
+## Examples
+
+You find different usage tutorials in our example project https://github.com/stomp-php/stomp-php-examples.
+
+### Connection Probing
+
+It's hard to find out if a socket connection is still working or not, Stomp allows us to use heartbeats to test if client
+and server are ready to serve messages.
+
+You should use `\Stomp\Network\Observer\ServerAliveObserver` or `\Stomp\Network\Observer\HeartbeatEmitter` to receive or
+send heartbeats. Doing so will ensure that your client will detect a broken connection in time. Please have a look at
+https://github.com/stomp-php/stomp-php-examples for some example code with additonal comments.
+
+## Replace fusesource/stomp-php
+
+If you used `fusesource/stomp-php` before, you can use our `2.x` versions.
+
+```json
+ "require": {
+ "stomp-php/stomp-php": "2.*"
+ }
+```
+
+## Contributing
+
+We code in `PSR2`, please use our predefined `pre_commit.sh` hook.
+
+## Tests
+
+To run the tests you first need to fetch the dependencies for the test suite
+via composer:
+
+ $ php composer.phar install
+
+The functional testsuite is divided into three broker versions.
+Currently it's running on `ActiveMq` (Port 61010), `Apollo` (61020), `RabbitMq` (61030).
+Apollo should be configured to use admin:password and RabbitMq to guest:guest.
+While ActiveMq must be configured to use no login at all.
+
+You can setup all brokers by running `travisci/bin/start.sh`. Stop them by `travisci/bin/stop.sh`. (Docker is required.)
+
+If you only like to run the functional generic tests, ensure Apollo is configured.
+A basic setup can be achieved by running `./travisci/bin/apollo-mq.sh 1.7.1`.
+(If you want to create a local running broker, you find the config / setup at `travisci/docker/apollo-mq/`)
+
+## Licence
+
+[Apache License Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
\ No newline at end of file
--- /dev/null
+{
+ "name": "stomp-php/stomp-php",
+ "description": "stomp support for PHP",
+ "keywords": ["messaging", "stomp", "jms", "activemq", "rabbitmq", "apollomq"],
+ "homepage": "http://github.com/stomp-php/stomp-php",
+ "license": "Apache-2.0",
+ "authors": [
+ {
+ "name": "Dejan Bosnanac",
+ "email": "dejan@nighttale.net",
+ "homepage": "http://www.nighttale.net"
+ },
+ {
+ "name": "Sören Rohweder",
+ "email": "s.rohweder@blage.net",
+ "homepage": "http://www.monofone.de"
+ },
+ {
+ "name": "Jens Radtke",
+ "email": "swefl@fin-sn.de",
+ "homepage": "http://www.fin-sn.de"
+ }
+ ],
+ "config": {
+ "sort-packages": true
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7"
+ },
+ "autoload": {
+ "psr-4": {
+ "Stomp\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Stomp\\Tests\\": "tests/"
+ }
+ }
+}
--- /dev/null
+parameters:
+ level: 4
+ paths:
+ - src/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
+<phpunit
+ backupGlobals = "false"
+ backupStaticAttributes = "false"
+ colors = "true"
+ convertErrorsToExceptions = "true"
+ convertNoticesToExceptions = "true"
+ convertWarningsToExceptions = "true"
+ processIsolation = "false"
+ stopOnFailure = "false"
+ syntaxCheck = "false"
+ bootstrap = "tests/bootstrap.php" >
+ <filter>
+ <blacklist>
+ <directory>vendor</directory>
+ </blacklist>
+ <whitelist>
+ <directory>src</directory>
+ </whitelist>
+ </filter>
+ <testsuites>
+ <testsuite name="stomp-php Functional Test Suite">
+ <directory>tests/Functional/</directory>
+ </testsuite>
+ <testsuite name="stomp-php Special Test Cases Suite">
+ <directory>tests/Cases/</directory>
+ </testsuite>
+ <testsuite name="stomp-php Unit Test Suite">
+ <directory>tests/Unit/</directory>
+ </testsuite>
+ </testsuites>
+ <logging>
+ <log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
+ </logging>
+</phpunit>
--- /dev/null
+#!/usr/bin/env bash
+
+TEXT_RESET="\e[0m"
+TEXT_BOLD="\e[1;30m"
+TEXT_RED="\e[1;31m"
+TEXT_GREEN="\e[1;32m"
+
+function shc {
+ printf "${TEXT_BOLD}${1}${TEXT_RESET}"
+ sh $2
+
+ if [ $? -ne 0 ]; then
+ printf "${TEXT_RED}FAIL${TEXT_RESET}\n"
+ exit 1
+ else
+ printf "${TEXT_GREEN}OK${TEXT_RESET}\n"
+ fi
+}
+
+shc "PHPCS..." run_phpcs.sh
+shc "PHPUnit...\n" run_phpunit.sh
+
+# run_phpcpd.sh
--- /dev/null
+#!/usr/bin/env bash
+
+./vendor/bin/phpcs --extensions=php --standard=PSR2 --ignore=vendor src tests
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env bash
+
+./vendor/bin/phpunit --no-configuration tests/Unit/Stomp
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\ActiveMq;
+
+use Stomp\Protocol\Protocol;
+use Stomp\Protocol\Version;
+use Stomp\Transport\Frame;
+
+/**
+ * ActiveMq Stomp dialect.
+ *
+ *
+ * @package Stomp
+ * @author Hiram Chirino <hiram@hiramchirino.com>
+ * @author Dejan Bosanac <dejan@nighttale.net>
+ * @author Michael Caplan <mcaplan@labnet.net>
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ActiveMq extends Protocol
+{
+ /**
+ * Prefetch Size for subscriptions.
+ *
+ * @var int
+ */
+ private $prefetchSize = 1;
+
+ /**
+ * ActiveMq subscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param string $ack
+ * @param string $selector
+ * @param boolean|false $durable durable subscription
+ * @return Frame
+ */
+ public function getSubscribeFrame(
+ $destination,
+ $subscriptionId = null,
+ $ack = 'auto',
+ $selector = null,
+ $durable = false
+ ) {
+ $frame = parent::getSubscribeFrame($destination, $subscriptionId, $ack, $selector);
+ $frame['activemq.prefetchSize'] = $this->prefetchSize;
+ if ($durable) {
+ $frame['activemq.subscriptionName'] = $this->getClientId();
+ }
+ return $frame;
+ }
+
+ /**
+ * ActiveMq unsubscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param bool|false $durable
+ * @return Frame
+ */
+ public function getUnsubscribeFrame($destination, $subscriptionId = null, $durable = false)
+ {
+ $frame = parent::getUnsubscribeFrame($destination, $subscriptionId);
+ if ($durable) {
+ $frame['activemq.subscriptionName'] = $this->getClientId();
+ }
+ return $frame;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAckFrame(Frame $frame, $transactionId = null)
+ {
+ $ack = $this->createFrame('ACK');
+ $ack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $ack['id'] = $frame['ack'] ?: $frame->getMessageId();
+ } else {
+ $ack['message-id'] = $frame['ack'] ?: $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $ack['subscription'] = $frame['subscription'];
+ }
+ }
+ return $ack;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getNackFrame(Frame $frame, $transactionId = null, $requeue = null)
+ {
+ if ($requeue !== null) {
+ throw new \LogicException(
+ 'requeue header not supported by ActiveMQ. Please read ActiveMQ DLQ documentation.'
+ );
+ }
+ $nack = $this->createFrame('NACK');
+ $nack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $nack['id'] = $frame['ack'] ?: $frame->getMessageId();
+ } else {
+ $nack['message-id'] = $frame['ack'] ?: $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $nack['subscription'] = $frame['subscription'];
+ }
+ }
+ return $nack;
+ }
+
+
+ /**
+ * Prefetch Size for subscriptions
+ *
+ * @return int
+ */
+ public function getPrefetchSize()
+ {
+ return $this->prefetchSize;
+ }
+
+ /**
+ * Prefetch Size for subscriptions
+ *
+ * @param int $prefetchSize
+ * @return ActiveMq
+ */
+ public function setPrefetchSize($prefetchSize)
+ {
+ $this->prefetchSize = $prefetchSize;
+ return $this;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\ActiveMq\Mode;
+
+use Stomp\Broker\ActiveMq\ActiveMq;
+use Stomp\Broker\ActiveMq\Options;
+use Stomp\Broker\Exception\UnsupportedBrokerException;
+use Stomp\Client;
+
+/**
+ * ActiveMqMode
+ *
+ * @package Stomp\Broker\ActiveMq\Mode
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+abstract class ActiveMqMode
+{
+ /**
+ * @var Client
+ */
+ protected $client;
+
+
+ /**
+ * @var Options
+ */
+ protected $options;
+
+ /**
+ * ActiveMqMode constructor.
+ *
+ * @param Client $client
+ */
+ public function __construct(Client $client)
+ {
+ $this->options = new Options();
+ $this->client = $client;
+ }
+
+ /**
+ * @return ActiveMq
+ * @throws \Stomp\Broker\Exception\UnsupportedBrokerException
+ */
+ protected function getProtocol()
+ {
+ $protocol = $this->client->getProtocol();
+ if (!$protocol instanceof ActiveMq) {
+ throw new UnsupportedBrokerException($protocol, ActiveMq::class);
+ }
+ return $protocol;
+ }
+
+
+ /**
+ * @return Options
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * @param Options $options
+ * @return ActiveMqMode
+ */
+ public function setOptions(Options $options)
+ {
+ $this->options = $options;
+ return $this;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\ActiveMq\Mode;
+
+use Stomp\Client;
+use Stomp\Exception\StompException;
+use Stomp\States\Meta\Subscription;
+use Stomp\Transport\Frame;
+
+/**
+ * DurableSubscription for ActiveMq.
+ *
+ * @package Stomp\Broker\ActiveMq\Mode
+ * @author Jens Radtke <swefl.oss@fin-sn.de>l
+ */
+class DurableSubscription extends ActiveMqMode
+{
+ /**
+ * @var Subscription
+ */
+ private $subscription;
+
+ /**
+ * Subscription state
+ *
+ * @var bool
+ */
+ private $active = false;
+
+ /**
+ * DurableSubscription constructor.
+ * @param Client $client
+ * @param string $topic
+ * @param string $selector
+ * @param string $ack
+ * @throws StompException
+ */
+ public function __construct(Client $client, $topic, $selector = null, $ack = 'auto')
+ {
+ parent::__construct($client);
+ if (!$client->getClientId()) {
+ throw new StompException('Client must have been configured to use a specific clientId!');
+ }
+ $this->subscription = new Subscription($topic, $selector, $ack, $client->getClientId());
+ }
+
+ /**
+ * Init the subscription.
+ *
+ * @return void
+ */
+ public function activate()
+ {
+ if (!$this->active) {
+ $this->client->sendFrame(
+ $this->getProtocol()->getSubscribeFrame(
+ $this->subscription->getDestination(),
+ $this->subscription->getSubscriptionId(),
+ $this->subscription->getAck(),
+ $this->subscription->getSelector(),
+ true
+ )->addHeaders(
+ $this->options->getOptions()
+ )
+ );
+ $this->active = true;
+ }
+ }
+
+ /**
+ * Mark durable subscription as offline.
+ *
+ * @see deactivate() if you want to indicate that the consumer is permanently removed.
+ * @return void
+ */
+ public function inactive()
+ {
+ if ($this->active) {
+ $this->client->sendFrame(
+ $this->getProtocol()
+ ->getUnsubscribeFrame(
+ $this->subscription->getDestination(),
+ $this->subscription->getSubscriptionId()
+ )
+ );
+ $this->active = false;
+ }
+ }
+
+ /**
+ * Permanently remove durable subscription.
+ *
+ * @see inactive() if you just want to indicate that the consumer is offline now.
+ * @return void
+ */
+ public function deactivate()
+ {
+ if ($this->active) {
+ $this->inactive();
+ $this->client->sendFrame(
+ $this->getProtocol()
+ ->getUnsubscribeFrame(
+ $this->subscription->getDestination(),
+ $this->subscription->getSubscriptionId(),
+ true
+ )
+ );
+ $this->active = false;
+ }
+ }
+
+ /**
+ * Reads a frame.
+ *
+ * @return false|\Stomp\Transport\Frame
+ */
+ public function read()
+ {
+ return $this->client->readFrame();
+ }
+
+ /**
+ * Ack a frame.
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function ack(Frame $frame)
+ {
+ $this->client->sendFrame($this->getProtocol()->getAckFrame($frame));
+ }
+
+ /**
+ * Nack a frame.
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function nack(Frame $frame)
+ {
+ $this->client->sendFrame($this->getProtocol()->getNackFrame($frame));
+ }
+
+ /**
+ * Returns the Subscription details.
+ *
+ * @return Subscription
+ */
+ public function getSubscription()
+ {
+ return $this->subscription;
+ }
+
+ /**
+ * Check if subscription is currently active.
+ *
+ * @return boolean
+ */
+ public function isActive()
+ {
+ return $this->active;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\ActiveMq;
+
+use ArrayAccess;
+
+/**
+ * Options for ActiveMq Stomp
+ *
+ * For more details visit http://activemq.apache.org/stomp.html
+ *
+ * @package Stomp\Broker\ActiveMq
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Options implements ArrayAccess
+{
+ private $extensions = [
+ 'activemq.dispatchAsync',
+ 'activemq.exclusive',
+ 'activemq.maximumPendingMessageLimit',
+ 'activemq.noLocal',
+ 'activemq.prefetchSize',
+ 'activemq.priority',
+ 'activemq.retroactive',
+ ];
+
+ private $options = [];
+
+ /**
+ * Options constructor.
+ * @param array $options
+ */
+ public function __construct(array $options = [])
+ {
+ foreach ($options as $key => $value) {
+ $this[$key] = $value;
+ }
+ }
+
+ public function offsetExists($offset)
+ {
+ return isset($this->options[$offset]);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->options[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ if (in_array($offset, $this->extensions, true)) {
+ $this->options[$offset] = $value;
+ }
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->options[$offset]);
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+
+ public function activateRetroactive()
+ {
+ $this['activemq.retroactive'] = 'true';
+ return $this;
+ }
+ public function activateExclusive()
+ {
+ $this['activemq.exclusive'] = 'true';
+ return $this;
+ }
+
+ public function activateDispatchAsync()
+ {
+ $this['activemq.dispatchAsync'] = 'true';
+ return $this;
+ }
+
+ public function setPriority($priority)
+ {
+ $this['activemq.priority'] = $priority;
+ return $this;
+ }
+
+
+ public function setPrefetchSize($size)
+ {
+ $this['activemq.prefetchSize'] = max($size, 1);
+ return $this;
+ }
+
+
+ public function activateNoLocal()
+ {
+ $this['activemq.noLocal'] = 'true';
+ return $this;
+ }
+
+ public function setMaximumPendingLimit($limit)
+ {
+ $this['activemq.maximumPendingMessageLimit'] = $limit;
+ return $this;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\Apollo;
+
+use Stomp\Protocol\Protocol;
+use Stomp\Protocol\Version;
+use Stomp\Transport\Frame;
+
+/**
+ * Apollo Stomp dialect.
+ *
+ * @package Stomp
+ * @author András Rutkai <riskawarrior@live.com>
+ */
+class Apollo extends Protocol
+{
+ /**
+ * Apollo subscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param string $ack
+ * @param string $selector
+ * @param boolean $durable durable subscription
+ * @return \Stomp\Transport\Frame
+ */
+ public function getSubscribeFrame(
+ $destination,
+ $subscriptionId = null,
+ $ack = 'auto',
+ $selector = null,
+ $durable = false
+ ) {
+ $frame = parent::getSubscribeFrame($destination, $subscriptionId, $ack, $selector);
+ if ($this->hasClientId() && $durable) {
+ $frame['persistent'] = 'true';
+ }
+ return $frame;
+ }
+
+ /**
+ * Apollo unsubscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param bool|false $durable
+ * @return \Stomp\Transport\Frame
+ */
+ public function getUnsubscribeFrame($destination, $subscriptionId = null, $durable = false)
+ {
+ $frame = parent::getUnsubscribeFrame($destination, $subscriptionId);
+ if ($durable) {
+ $frame['persistent'] = 'true';
+ }
+ return $frame;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAckFrame(Frame $frame, $transactionId = null)
+ {
+ $ack = $this->createFrame('ACK');
+ $ack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $ack['id'] = $frame['ack'] ?: $frame->getMessageId();
+ } else {
+ $ack['message-id'] = $frame['ack'] ?: $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $ack['subscription'] = $frame['subscription'];
+ }
+ }
+ return $ack;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getNackFrame(Frame $frame, $transactionId = null, $requeue = null)
+ {
+ if ($requeue !== null) {
+ throw new \LogicException('requeue header not supported');
+ }
+ $nack = $this->createFrame('NACK');
+ $nack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $nack['id'] = $frame['ack'] ?: $frame->getMessageId();
+ } else {
+ $nack['message-id'] = $frame['ack'] ?: $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $nack['subscription'] = $frame['subscription'];
+ }
+ }
+ return $nack;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\Apollo\Mode;
+
+use Stomp\Broker\Apollo\Apollo;
+use Stomp\Broker\Exception\UnsupportedBrokerException;
+use Stomp\Client;
+use Stomp\States\Meta\Subscription;
+use Stomp\Util\IdGenerator;
+
+/**
+ * QueueBrowser ApolloMq util to browse a queue without removing messages from it.
+ *
+ * @see http://activemq.apache.org/apollo/documentation/stomp-manual.html#Browsing_Subscriptions
+ *
+ * @package Stomp\Broker\Apollo\Mode
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class QueueBrowser
+{
+ /**
+ * @var Client
+ */
+ private $client;
+
+ /**
+ * @var bool
+ */
+ private $stopOnEnd;
+
+ /**
+ * @var Subscription
+ */
+ private $subscription;
+
+ /**
+ * @var bool
+ */
+ private $active = false;
+
+ /**
+ * @var bool
+ */
+ private $reachedEnd = false;
+
+ /**
+ * QueueBrowser constructor.
+ *
+ * @param Client $client
+ * @param string $destination
+ * @param bool $stopOnEnd
+ */
+ public function __construct(Client $client, $destination, $stopOnEnd = true)
+ {
+ $this->stopOnEnd = $stopOnEnd;
+ $this->client = $client;
+ $this->stopOnEnd = $stopOnEnd;
+ $this->subscription = new Subscription($destination, null, 'auto', IdGenerator::generateId());
+ }
+
+ /**
+ * Protocol
+ * @return Apollo
+ * @throws UnsupportedBrokerException
+ */
+ final protected function getProtocol()
+ {
+ $protocol = $this->client->getProtocol();
+ if (!$protocol instanceof Apollo) {
+ throw new UnsupportedBrokerException($protocol, Apollo::class);
+ }
+ return $protocol;
+ }
+
+ /**
+ * Headers used in subscribe.
+ *
+ * @return array
+ */
+ protected function getHeader()
+ {
+ return [
+ 'browser' => 'true',
+ 'browser-end' => $this->stopOnEnd ? 'true' : 'false',
+ ];
+ }
+
+ /**
+ * Initialize subscription.
+ *
+ * @return void
+ */
+ public function subscribe()
+ {
+ if (!$this->active) {
+ $this->reachedEnd = false;
+ $this->client->sendFrame(
+ $this->getProtocol()->getSubscribeFrame(
+ $this->subscription->getDestination(),
+ $this->subscription->getSubscriptionId(),
+ $this->subscription->getAck(),
+ $this->subscription->getSelector(),
+ false
+ )->addHeaders($this->getHeader())
+ );
+ $this->active = true;
+ }
+ }
+
+ /**
+ * End subscription.
+ *
+ * @return void
+ */
+ public function unsubscribe()
+ {
+ if ($this->active) {
+ $this->client->sendFrame(
+ $this->getProtocol()->getUnsubscribeFrame(
+ $this->subscription->getDestination(),
+ $this->subscription->getSubscriptionId(),
+ false
+ )
+ );
+ $this->active = false;
+ }
+ }
+
+ /**
+ * Read next message.
+ *
+ * @return bool|false|\Stomp\Transport\Frame
+ */
+ public function read()
+ {
+ if (!$this->active || $this->reachedEnd) {
+ return false;
+ }
+ if ($frame = $this->client->readFrame()) {
+ if ($this->stopOnEnd && $frame['browser'] == 'end') {
+ $this->reachedEnd = true;
+ return false;
+ }
+ }
+ return $frame;
+ }
+
+ /**
+ * Last message was received (can only be true if 'StopAtEnd' is enabled!)
+ *
+ * @return boolean
+ */
+ public function hasReachedEnd()
+ {
+ return $this->reachedEnd;
+ }
+
+ /**
+ * Subscription has been initialized.
+ *
+ * @return boolean
+ */
+ public function isActive()
+ {
+ return $this->active;
+ }
+
+ /**
+ * Subscription details.
+ *
+ * @return Subscription
+ */
+ public function getSubscription()
+ {
+ return $this->subscription;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function __destruct()
+ {
+ IdGenerator::releaseId($this->subscription->getSubscriptionId());
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\Apollo\Mode;
+
+use Stomp\Client;
+
+/**
+ * SequenceQueueBrowser ApolloMq util to browse a queue sequence based without removing messages from it.
+ *
+ * @see http://activemq.apache.org/apollo/documentation/stomp-manual.html
+ * #Using_Queue_Browsers_to_Implement_Durable_Topic_Subscriptions
+ *
+ * @package Stomp\Broker\Apollo\Mode
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class SequenceQueueBrowser extends QueueBrowser
+{
+ /**
+ * Browser start at head at current queue
+ */
+ const START_HEAD = 0;
+ /**
+ * Browser start at for new messages in queue
+ */
+ const START_NEW = -1;
+
+ /**
+ * @var int
+ */
+ private $startAt;
+
+ /**
+ * Current offset.
+ *
+ * @var null|int
+ */
+ private $seq;
+
+ /**
+ * SequenceQueueBrowser constructor.
+ *
+ * @param Client $client
+ * @param string $destination
+ * @param int $startAt
+ * @param bool $stopOnEnd
+ */
+ public function __construct(Client $client, $destination, $startAt = self::START_HEAD, $stopOnEnd = true)
+ {
+ $this->startAt = $startAt;
+ parent::__construct($client, $destination, $stopOnEnd);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getHeader()
+ {
+ return parent::getHeader() + ['include-seq' => 'seq', 'from-seq' => $this->startAt];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function read()
+ {
+ if ($frame = parent::read()) {
+ $this->seq = $frame['seq'];
+ }
+ return $frame;
+ }
+
+ /**
+ * Returns the last received sequence.
+ *
+ * @return null|int
+ */
+ public function getSeq()
+ {
+ return $this->seq;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\Exception;
+
+use Stomp\Exception\StompException;
+use Stomp\Protocol\Protocol;
+
+/**
+ * UnsupportedBrokerException
+ *
+ * Indicate that given broker is not supported.
+ *
+ * @package Stomp\Broker\Exception
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class UnsupportedBrokerException extends StompException
+{
+
+ /**
+ * @param Protocol $detectedProtocol
+ * @param string $expectedProtocol
+ */
+ public function __construct(Protocol $detectedProtocol, $expectedProtocol)
+ {
+ parent::__construct(
+ sprintf('The current broker (%s) is no %s.', get_class($detectedProtocol), $expectedProtocol)
+ );
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\OpenMq;
+
+use Stomp\Protocol\Protocol;
+use Stomp\Transport\Frame;
+use Stomp\Protocol\Version;
+
+/**
+ * OpenMq Stomp dialect.
+ *
+ * @package Stomp
+ * @author Markus Staab <maggus.staab@googlemail.com>
+ */
+class OpenMq extends Protocol
+{
+ /**
+ * @inheritdoc
+ */
+ public function getAckFrame(Frame $frame, $transactionId = null)
+ {
+ $ack = $this->createFrame('ACK');
+ $ack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $ack['id'] = $frame->getMessageId();
+ } else {
+ $ack['message-id'] = $frame->getMessageId();
+ }
+ // spec quote: "ACK should always specify a "subscription" header for the subscription id
+ // that the message to be acked was delivered to ."
+ // see https://mq.java.net/4.4-content/stomp-funcspec.html
+ $ack['subscription'] = $frame['subscription'];
+ return $ack;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Broker\RabbitMq;
+
+use Stomp\Exception\StompException;
+use Stomp\Protocol\Protocol;
+use Stomp\Transport\Frame;
+use Stomp\Protocol\Version;
+
+/**
+ * RabbitMq Stomp dialect.
+ *
+ *
+ * @package Stomp
+ * @author Hiram Chirino <hiram@hiramchirino.com>
+ * @author Dejan Bosanac <dejan@nighttale.net>
+ * @author Michael Caplan <mcaplan@labnet.net>
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class RabbitMq extends Protocol
+{
+
+ /**
+ * Prefetch Size for subscriptions.
+ *
+ * @var int
+ */
+
+ private $prefetchCount = 1;
+
+ /**
+ * RabbitMq subscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param string $ack
+ * @param string $selector
+ * @param boolean|false $durable durable subscription
+ * @return Frame
+ */
+ public function getSubscribeFrame(
+ $destination,
+ $subscriptionId = null,
+ $ack = 'auto',
+ $selector = null,
+ $durable = false
+ ) {
+ $frame = parent::getSubscribeFrame($destination, $subscriptionId, $ack, $selector);
+ $frame['prefetch-count'] = $this->prefetchCount;
+ if ($durable) {
+ $frame['persistent'] = 'true';
+ }
+ return $frame;
+ }
+
+ /**
+ * RabbitMq unsubscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param bool|false $durable
+ * @return \Stomp\Transport\Frame
+ */
+ public function getUnsubscribeFrame($destination, $subscriptionId = null, $durable = false)
+ {
+ $frame = parent::getUnsubscribeFrame($destination, $subscriptionId);
+ if ($durable) {
+ $frame['persistent'] = 'true';
+ }
+ return $frame;
+ }
+
+
+ /**
+ * Prefetch Count for subscriptions
+ *
+ * @return int
+ */
+ public function getPrefetchCount()
+ {
+ return $this->prefetchCount;
+ }
+
+ /**
+ * Prefetch Count for subscriptions
+ *
+ * @param int $prefetchCount
+ */
+ public function setPrefetchCount($prefetchCount)
+ {
+ $this->prefetchCount = $prefetchCount;
+ }
+
+
+ /**
+ * Get message not acknowledge frame.
+ *
+ * @param \Stomp\Transport\Frame $frame
+ * @param string $transactionId
+ * @param bool $requeue Requeue header supported on RabbitMQ >= 3.4, ignored in prior versions
+ * @return \Stomp\Transport\Frame
+ * @throws StompException
+ */
+ public function getNackFrame(Frame $frame, $transactionId = null, $requeue = null)
+ {
+ if ($this->getVersion() === Version::VERSION_1_0) {
+ throw new StompException('Stomp Version 1.0 has no support for NACK Frames.');
+ }
+ $nack = $this->createFrame('NACK');
+ if ($requeue !== null) {
+ $nack->addHeaders(['requeue' => $requeue ? 'true' : 'false']);
+ }
+ $nack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $nack['id'] = $frame->getMessageId();
+ } else {
+ $nack['message-id'] = $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $nack['subscription'] = $frame['subscription'];
+ }
+ }
+
+ $nack['message-id'] = $frame->getMessageId();
+ return $nack;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp;
+
+use Stomp\Exception\ConnectionException;
+use Stomp\Exception\MissingReceiptException;
+use Stomp\Exception\StompException;
+use Stomp\Exception\UnexpectedResponseException;
+use Stomp\Network\Connection;
+use Stomp\Protocol\Protocol;
+use Stomp\Protocol\Version;
+use Stomp\Transport\Frame;
+
+/**
+ * Stomp Client
+ *
+ * This is the minimal implementation of a Stomp Client, it allows to send and receive Frames using the Stomp Protocol.
+ *
+ * @package Stomp
+ * @author Hiram Chirino <hiram@hiramchirino.com>
+ * @author Dejan Bosanac <dejan@nighttale.net>
+ * @author Michael Caplan <mcaplan@labnet.net>
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Client
+{
+ /**
+ * Perform request synchronously
+ *
+ * @var boolean
+ */
+ private $sync = true;
+
+
+ /**
+ * Client id used for durable subscriptions
+ *
+ * @var string
+ */
+ private $clientId;
+
+ /**
+ * Connection session id
+ *
+ * @var string|null
+ */
+ private $sessionId;
+
+ /**
+ * Frames that have been read but not processed yet.
+ *
+ * @var Frame[]
+ */
+ private $unprocessedFrames = [];
+
+ /**
+ * @var Connection|null
+ */
+ private $connection;
+
+ /**
+ *
+ * @var Protocol|null
+ */
+ private $protocol;
+
+ /**
+ * Seconds to wait for a receipt.
+ *
+ * @var float
+ */
+ private $receiptWait = 2;
+
+ /**
+ *
+ * @var string
+ */
+ private $login;
+
+ /**
+ *
+ * @var string
+ */
+ private $passcode;
+
+
+ /**
+ *
+ * @var array
+ */
+ private $versions = [Version::VERSION_1_0, Version::VERSION_1_1, Version::VERSION_1_2];
+
+ /**
+ *
+ * @var string
+ */
+ private $host;
+
+ /**
+ *
+ * @var int[]
+ */
+ private $heartbeat = [0, 0];
+
+ /**
+ * @var bool
+ */
+ private $isConnecting = false;
+
+ /**
+ * Constructor
+ *
+ * @param string|Connection $broker Broker URL or a connection
+ * @see Connection::__construct()
+ */
+ public function __construct($broker)
+ {
+ $this->connection = $broker instanceof Connection ? $broker : new Connection($broker);
+ }
+
+ /**
+ * Configure versions to support.
+ *
+ * @param array $versions defaults to all client supported versions
+ */
+ public function setVersions(array $versions)
+ {
+ $this->versions = $versions;
+ }
+
+ /**
+ * Configure the login to use.
+ *
+ * @param string $login
+ * @param string $passcode
+ */
+ public function setLogin($login, $passcode)
+ {
+ $this->login = $login;
+ $this->passcode = $passcode;
+ }
+
+ /**
+ * Sets an fixed vhostname, which will be passed on connect as header['host'].
+ *
+ * (null = Default value is the hostname determined by connection.)
+ *
+ * @param string $host
+ */
+ public function setVhostname($host = null)
+ {
+ $this->host = $host;
+ }
+
+ /**
+ * Set the desired heartbeat for the connection.
+ *
+ * A heartbeat is a specific message that will be send / received when no other data is send / received
+ * within an interval - to indicate that the connection is still stable. If client and server agree on a beat and
+ * the interval passes without any data activity / beats the connection will be considered as broken and closed.
+ *
+ * If you want to make sure that the server is still available, you should use the ServerAliveObserver
+ * in combination with an requested server heartbeat interval.
+ *
+ * If you define a heartbeat for client side, you must assure that
+ * your application will send data within the interval.
+ * You can add \Stomp\Network\Observer\HeartbeatEmitter to your connection in order to send beats automatically.
+ *
+ * If you don't use HeartbeatEmitter you must either send messages within the interval
+ * or make calls to Connection::sendAlive()
+ *
+ * @param int $send
+ * Number of milliseconds between expected sending of heartbeats. 0 means
+ * no heartbeats sent.
+ * @param int $receive
+ * Number of milliseconds between expected receipt of heartbeats. 0 means
+ * no heartbeats expected. (not yet supported by this client)
+ * @see \Stomp\Network\Observer\ServerAliveObserver
+ * @see \Stomp\Network\Observer\HeartbeatEmitter
+ * @see \Stomp\Network\Connection::sendAlive()
+ */
+ public function setHeartbeat($send = 0, $receive = 0)
+ {
+ $this->heartbeat = [$send, $receive];
+ }
+
+ /**
+ * Connect to server
+ *
+ * @return boolean
+ * @throws StompException
+ * @see setVhostname
+ */
+ public function connect()
+ {
+ if ($this->isConnected()) {
+ return true;
+ }
+ $this->isConnecting = true;
+ $this->connection->connect();
+ $this->connection->getParser()->legacyMode(true);
+ $this->protocol = new Protocol($this->clientId);
+
+ $this->host = $this->host ?: $this->connection->getHost();
+
+ $connectFrame = $this->protocol->getConnectFrame(
+ $this->login,
+ $this->passcode,
+ $this->versions,
+ $this->host,
+ $this->heartbeat
+ );
+ $this->sendFrame($connectFrame, false);
+
+ if ($frame = $this->getConnectedFrame()) {
+ $version = new Version($frame);
+
+ if ($version->hasVersion(Version::VERSION_1_1)) {
+ $this->connection->getParser()->legacyMode(false);
+ }
+
+ $this->sessionId = $frame['session'];
+ $this->protocol = $version->getProtocol($this->clientId);
+ $this->isConnecting = false;
+ return true;
+ }
+ throw new ConnectionException('Connection not acknowledged');
+ }
+
+ /**
+ * Returns the next available frame from the connection, respecting the connect timeout.
+ *
+ * @return null|Frame
+ * @throws ConnectionException
+ * @throws Exception\ErrorFrameException
+ */
+ private function getConnectedFrame()
+ {
+ $deadline = microtime(true) + $this->getConnection()->getConnectTimeout();
+ do {
+ if ($frame = $this->connection->readFrame()) {
+ return $frame;
+ }
+ } while (microtime(true) <= $deadline);
+
+ return null;
+ }
+
+ /**
+ * Send a message to a destination in the messaging system
+ *
+ * @param string $destination Destination queue
+ * @param string|Frame $msg Message
+ * @param array $header
+ * @param boolean $sync Perform request synchronously
+ * @return boolean
+ */
+ public function send($destination, $msg, array $header = [], $sync = null)
+ {
+ if (!$msg instanceof Frame) {
+ return $this->send($destination, new Frame('SEND', $header, $msg), [], $sync);
+ }
+
+ $msg->addHeaders($header);
+ $msg['destination'] = $destination;
+ return $this->sendFrame($msg, $sync);
+ }
+
+ /**
+ * Send a frame.
+ *
+ * @param Frame $frame
+ * @param boolean $sync
+ * @return boolean
+ */
+ public function sendFrame(Frame $frame, $sync = null)
+ {
+ if (!$this->isConnecting && !$this->isConnected()) {
+ $this->connect();
+ }
+ // determine if client was configured to write sync or not
+ $writeSync = $sync !== null ? $sync : $this->sync;
+ if ($writeSync) {
+ return $this->sendFrameExpectingReceipt($frame);
+ } else {
+ return $this->connection->writeFrame($frame);
+ }
+ }
+
+
+ /**
+ * Write frame to server and expect an matching receipt frame
+ *
+ * @param Frame $stompFrame
+ * @return bool
+ */
+ protected function sendFrameExpectingReceipt(Frame $stompFrame)
+ {
+ $receipt = md5(microtime());
+ $stompFrame['receipt'] = $receipt;
+ $this->connection->writeFrame($stompFrame);
+ return $this->waitForReceipt($receipt);
+ }
+
+
+ /**
+ * Wait for an receipt
+ *
+ * @param string $receipt
+ * @return boolean
+ * @throws UnexpectedResponseException If response has an invalid receipt.
+ * @throws MissingReceiptException If no receipt is received.
+ */
+ protected function waitForReceipt($receipt)
+ {
+ $stopAfter = $this->calculateReceiptWaitEnd();
+ while (true) {
+ if ($frame = $this->connection->readFrame()) {
+ if ($frame->getCommand() == 'RECEIPT') {
+ if ($frame['receipt-id'] == $receipt) {
+ return true;
+ } else {
+ throw new UnexpectedResponseException($frame, sprintf('Expected receipt id %s', $receipt));
+ }
+ } else {
+ $this->unprocessedFrames[] = $frame;
+ }
+ }
+ if (microtime(true) >= $stopAfter) {
+ break;
+ }
+ }
+ throw new MissingReceiptException($receipt);
+ }
+
+ /**
+ * Returns the timestamp with micro time to stop wait for a receipt.
+ *
+ * @return float
+ */
+ protected function calculateReceiptWaitEnd()
+ {
+ return microtime(true) + $this->receiptWait;
+ }
+
+
+ /**
+ * Read response frame from server
+ *
+ * @return Frame|false when no frame to read
+ */
+ public function readFrame()
+ {
+ return array_shift($this->unprocessedFrames) ?: $this->connection->readFrame();
+ }
+
+ /**
+ * Graceful disconnect from the server
+ * @param bool $sync
+ * @return void
+ */
+ public function disconnect($sync = false)
+ {
+ try {
+ if ($this->connection && $this->connection->isConnected()) {
+ if ($this->protocol) {
+ $this->sendFrame($this->protocol->getDisconnectFrame(), $sync);
+ }
+ }
+ } catch (StompException $ex) {
+ // nothing!
+ }
+ if ($this->connection) {
+ $this->connection->disconnect();
+ }
+
+ $this->sessionId = null;
+ $this->unprocessedFrames = [];
+ $this->protocol = null;
+ $this->isConnecting = false;
+ }
+
+ /**
+ * Current stomp session ID
+ *
+ * @return string|null
+ */
+ public function getSessionId()
+ {
+ return $this->sessionId;
+ }
+
+ /**
+ * Graceful object destruction
+ *
+ */
+ public function __destruct()
+ {
+ $this->disconnect();
+ }
+
+ /**
+ * Check if client session has ben established
+ *
+ * @return boolean
+ */
+ public function isConnected()
+ {
+ return !empty($this->sessionId) && $this->connection->isConnected();
+ }
+
+ /**
+ * Get the used connection.
+ *
+ * @return Connection
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * Get the currently used protocol.
+ *
+ * @return null|\Stomp\Protocol\Protocol
+ */
+ public function getProtocol()
+ {
+ if (!$this->isConnecting && !$this->isConnected()) {
+ $this->connect();
+ }
+ return $this->protocol;
+ }
+
+ /**
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->clientId;
+ }
+
+ /**
+ * @param string $clientId
+ * @return Client
+ */
+ public function setClientId($clientId)
+ {
+ $this->clientId = $clientId;
+ return $this;
+ }
+
+
+ /**
+ * Set seconds to wait for a receipt.
+ *
+ * @param float $seconds
+ */
+ public function setReceiptWait($seconds)
+ {
+ $this->receiptWait = $seconds;
+ }
+
+ /**
+ * Check if client runs in synchronized mode, which is the default operation mode.
+ *
+ * @return boolean
+ */
+ public function isSync()
+ {
+ return $this->sync;
+ }
+
+ /**
+ * Toggle synchronized mode.
+ *
+ * @param boolean $sync
+ */
+ public function setSync($sync)
+ {
+ $this->sync = $sync;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Exception;
+
+/**
+ * Any kind of connection problems.
+ *
+ *
+ * @package Stomp
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ConnectionException extends StompException
+{
+ /**
+ *
+ * @var array
+ */
+ private $connectionInfo;
+
+ /**
+ *
+ * @param string $info
+ * @param array $connection
+ * @param ConnectionException $previous
+ */
+ public function __construct($info, array $connection = [], ConnectionException $previous = null)
+ {
+ $this->connectionInfo = $connection;
+
+ $host = ($previous ? $previous->getHostname() : null) ?: $this->getHostname();
+
+ if ($host) {
+ $info = sprintf('%s (Host: %s)', $info, $host);
+ }
+ parent::__construct($info, 0, $previous);
+ }
+
+
+ /**
+ * Active used connection.
+ *
+ * @return array
+ */
+ public function getConnectionInfo()
+ {
+ return $this->connectionInfo;
+ }
+
+
+ protected function getHostname()
+ {
+ return isset($this->connectionInfo['host']) ? $this->connectionInfo['host'] : null;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Exception;
+
+use Stomp\Transport\Frame;
+
+/**
+ * Stomp server send us an error frame.
+ *
+ *
+ * @package Stomp
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ErrorFrameException extends StompException
+{
+ /**
+ *
+ * @var Frame
+ */
+ private $frame;
+
+ /**
+ *
+ * @param Frame $frame
+ */
+ public function __construct(Frame $frame)
+ {
+ $this->frame = $frame;
+ parent::__construct(
+ sprintf('Error "%s"', $frame['message'])
+ );
+ }
+
+ /**
+ *
+ * @return Frame
+ */
+ public function getFrame()
+ {
+ return $this->frame;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Exception;
+
+/**
+ * Exception that occurs, when a frame receipt was not received.
+ *
+ *
+ * @package Stomp
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class MissingReceiptException extends StompException
+{
+ /**
+ * @var string
+ */
+ private $receiptId;
+
+ /**
+ *
+ * @param string $receiptId
+ */
+ public function __construct($receiptId)
+ {
+ $this->receiptId = $receiptId;
+ parent::__construct(
+ sprintf(
+ 'Missing receipt Frame for id "%s". Maybe the queue server is under heavy load. ' .
+ 'Try to increase timeouts.',
+ $receiptId
+ )
+ );
+ }
+
+ /**
+ * Expected receipt id.
+ *
+ * @return String
+ */
+ public function getReceiptId()
+ {
+ return $this->receiptId;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Exception;
+
+use Exception;
+
+/**
+ * Base exception for all special stomp exceptions.
+ *
+ * @package Stomp
+ */
+class StompException extends Exception
+{
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Exception;
+
+use Stomp\Transport\Frame;
+
+/**
+ * Exception that occurs, when a frame / response was received that was not expected at this moment.
+ *
+ *
+ * @package Stomp
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class UnexpectedResponseException extends StompException
+{
+ /**
+ *
+ * @var Frame
+ */
+ private $frame;
+
+ /**
+ *
+ * @param Frame $frame
+ * @param string $expectedInfo
+ */
+ public function __construct(Frame $frame, $expectedInfo)
+ {
+ $this->frame = $frame;
+ parent::__construct(sprintf('Unexpected response received. %s', $expectedInfo));
+ }
+
+ /**
+ *
+ * @return Frame
+ */
+ public function getFrame()
+ {
+ return $this->frame;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network;
+
+use Stomp\Exception\ConnectionException;
+use Stomp\Exception\ErrorFrameException;
+use Stomp\Network\Observer\ConnectionObserverCollection;
+use Stomp\Transport\Frame;
+use Stomp\Transport\Parser;
+
+/**
+ * A Stomp Connection
+ *
+ * @package Stomp
+ * @author Hiram Chirino <hiram@hiramchirino.com>
+ * @author Dejan Bosanac <dejan@nighttale.net>
+ * @author Michael Caplan <mcaplan@labnet.net>
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Connection
+{
+ /**
+ * Default ActiveMq port
+ */
+ const DEFAULT_PORT = 61613;
+
+ /**
+ * Host schemes.
+ *
+ * @var array[]
+ */
+ private $hosts = [];
+
+ /**
+ * Connection timeout in seconds.
+ *
+ * @var integer
+ */
+ private $connectTimeout;
+
+ /**
+ * Timeout (seconds) that are applied on write calls.
+ *
+ * @var integer
+ */
+ private $writeTimeout = 3;
+
+ /**
+ * Using persistent connection for creating socket
+ *
+ * @var bool
+ */
+ private $persistentConnection = false;
+
+ /**
+ * Connection read wait timeout.
+ *
+ * 0 => seconds
+ * 1 => milliseconds
+ *
+ * @var array
+ */
+ private $readTimeout = [60, 0];
+
+ /**
+ * Connection options.
+ *
+ * @var array
+ */
+ private $params = [
+ 'randomize' => false // connect to one host from list in random order
+ ];
+
+ /**
+ * Active connection resource.
+ *
+ * @var resource|null
+ */
+ private $connection;
+
+ /**
+ * Connected host info.
+ *
+ * @var array
+ */
+ private $activeHost = [];
+
+ /**
+ * Stream Context used for client connection
+ *
+ * @see http://php.net/manual/de/function.stream-context-create.php
+ *
+ * @var array
+ */
+ private $context = [];
+
+ /**
+ * Frame parser
+ *
+ * @var Parser
+ */
+ private $parser;
+
+ /**
+ * Host connected to.
+ *
+ * @var String
+ */
+ private $host;
+
+ /**
+ * @var ConnectionObserverCollection
+ */
+ private $observers;
+
+ /**
+ * Maximum number of bytes to write to a resource.
+ *
+ * @var int
+ */
+ private $maxWriteBytes = 8192;
+
+ /**
+ * Maximum number of bytes to read from a resource.
+ *
+ * @var int
+ */
+ private $maxReadBytes = 8192;
+
+ /**
+ * Alive Signal
+ */
+ const ALIVE = "\n";
+
+ /**
+ * @var callable|null
+ */
+ private $waitCallback;
+
+ /**
+ * Initialize connection
+ *
+ * Example broker uri
+ * - Use only one broker uri: tcp://localhost:61614
+ * - use failover in given order: failover://(tcp://localhost:61614,ssl://localhost:61612)
+ * - use brokers in random order: failover://(tcp://localhost:61614,ssl://localhost:61612)?randomize=true
+ *
+ * @param string $brokerUri
+ * @param integer $connectionTimeout in seconds
+ * @param array $context stream context
+ * @throws ConnectionException
+ */
+ public function __construct($brokerUri, $connectionTimeout = 1, array $context = [])
+ {
+ $this->parser = new Parser();
+ $this->observers = new ConnectionObserverCollection();
+ $this->parser->setObserver($this->observers);
+ $this->connectTimeout = $connectionTimeout;
+ $this->context = $context;
+ $pattern = "|^(([a-zA-Z0-9]+)://)+\(*([a-zA-Z0-9\.:/i,-_]+)\)*\??([a-zA-Z0-9=&]*)$|i";
+ if (preg_match($pattern, $brokerUri, $matches)) {
+ $scheme = $matches[2];
+ $hosts = $matches[3];
+ $options = $matches[4];
+
+ if ($options) {
+ parse_str($options, $connectionOptions);
+ $this->params = $connectionOptions + $this->params;
+ }
+
+ if ($scheme != 'failover') {
+ $this->parseUrl($brokerUri);
+ } else {
+ $urls = explode(',', $hosts);
+ foreach ($urls as $url) {
+ $this->parseUrl($url);
+ }
+ }
+ }
+
+ if (empty($this->hosts)) {
+ throw new ConnectionException("Bad Broker URL {$brokerUri}. Check used scheme!");
+ }
+ }
+
+ /**
+ * Sets a wait callback that will be invoked when the connection is waiting for new data.
+ *
+ * This is a good place to call `pcntl_signal_dispatch()` if you need to ensure that your process signals in an
+ * interval that is lower as read timeout. You should also return `false` in your callback if you don't want the
+ * connection to continue waiting for data.
+ *
+ * @param callable|null $waitCallback
+ */
+ public function setWaitCallback($waitCallback)
+ {
+ if ($waitCallback !== null) {
+ if (!is_callable($waitCallback)) {
+ throw new \InvalidArgumentException('$waitCallback must be callable.');
+ }
+ }
+ $this->waitCallback = $waitCallback;
+ }
+
+ /**
+ * Returns the connect timeout in seconds.
+ *
+ * @return int
+ */
+ public function getConnectTimeout()
+ {
+ return $this->connectTimeout;
+ }
+
+ /**
+ * Returns the collection of observers of this connection.
+ *
+ * @return ConnectionObserverCollection
+ */
+ public function getObservers()
+ {
+ return $this->observers;
+ }
+
+ /**
+ * Parse a broker URL
+ *
+ * @param string $url Broker URL
+ * @return void
+ * @throws ConnectionException
+ */
+ private function parseUrl($url)
+ {
+ $parsed = parse_url($url);
+ if ($parsed === false) {
+ throw new ConnectionException('Unable to parse url '. $url);
+ }
+ array_push($this->hosts, $parsed + ['port' => '61613', 'scheme' => 'tcp']);
+ }
+
+ /**
+ * Set the read timeout
+ *
+ * @param integer $seconds seconds
+ * @param integer $microseconds microseconds (1μs = 0.000001s, ex. 500ms = 500000)
+ * @return void
+ */
+ public function setReadTimeout($seconds, $microseconds = 0)
+ {
+ $this->readTimeout[0] = $seconds;
+ $this->readTimeout[1] = $microseconds;
+ }
+
+ /**
+ * Returns the read timeout
+ *
+ * First element contains full seconds, second the microseconds part.
+ *
+ * @return array
+ */
+ public function getReadTimeout()
+ {
+ return $this->readTimeout;
+ }
+
+ /**
+ * Set the write timeout
+ *
+ * @param int $writeTimeout seconds
+ */
+ public function setWriteTimeout($writeTimeout)
+ {
+ $this->writeTimeout = $writeTimeout;
+ }
+
+ /**
+ * Set socket context
+ *
+ * @param array $context
+ * @return void
+ */
+ public function setContext(array $context)
+ {
+ $this->context = $context;
+ }
+
+ /**
+ * Set the maximum number of bytes to write to a resource
+ *
+ * This will be useful if you are suffering problems with OpenSSL or Amazon MQ
+ *
+ * @param int $maxWriteBytes bytes
+ */
+ public function setMaxWriteBytes($maxWriteBytes)
+ {
+ $this->maxWriteBytes = $maxWriteBytes;
+ }
+
+ /**
+ * Set the maximum number of bytes to read from a resource
+ *
+ * This will be useful if you are suffering problems with OpenSSL or Amazon MQ
+ *
+ * @param int $maxReadBytes bytes
+ */
+ public function setMaxReadBytes($maxReadBytes)
+ {
+ $this->maxReadBytes = $maxReadBytes;
+ }
+
+ /**
+ * Connect to an broker.
+ *
+ * @return boolean
+ * @throws ConnectionException
+ */
+ public function connect()
+ {
+ if (!$this->isConnected()) {
+ $this->connection = $this->getConnection();
+ }
+ return true;
+ }
+
+ /**
+ * @param boolean $persistentConnection
+ */
+ public function setPersistentConnection($persistentConnection)
+ {
+ $this->persistentConnection = $persistentConnection;
+ }
+
+ /**
+ * Get a connection.
+ *
+ * @return resource (stream)
+ * @throws ConnectionException
+ */
+ protected function getConnection()
+ {
+ $hosts = $this->getHostList();
+
+ while ($host = array_shift($hosts)) {
+ try {
+ return $this->connectSocket($host);
+ } catch (ConnectionException $connectionException) {
+ if (empty($hosts)) {
+ throw new ConnectionException("Could not connect to a broker", [], $connectionException);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the host list.
+ *
+ * @return array
+ */
+ protected function getHostList()
+ {
+ $hosts = array_values($this->hosts);
+ if ($this->params['randomize']) {
+ shuffle($hosts);
+ }
+ return $hosts;
+ }
+
+ /**
+ * Try to connect to given host.
+ *
+ * @param array $host
+ * @return resource (stream)
+ * @throws ConnectionException if connection setup fails
+ */
+ protected function connectSocket(array $host)
+ {
+ $this->activeHost = $host;
+ $errNo = null;
+ $errStr = null;
+
+ $context = stream_context_create($this->context);
+ $flags = STREAM_CLIENT_CONNECT;
+ if ($this->persistentConnection) {
+ $flags |= STREAM_CLIENT_PERSISTENT;
+ }
+ $socket = @stream_socket_client(
+ $host['scheme'] . '://' . $host['host'] . ':' . $host['port'],
+ $errNo,
+ $errStr,
+ $this->connectTimeout,
+ $flags,
+ $context
+ );
+
+
+ if (!is_resource($socket)) {
+ throw new ConnectionException(sprintf('Failed to connect. (%s: %s)', $errNo, $errStr), $host);
+ }
+
+ if (!@stream_set_blocking($socket, false)) {
+ throw new ConnectionException('Failed to set non blocking mode for stream.', $host);
+ }
+ $this->host = $host['host'];
+ return $socket;
+ }
+
+
+ /**
+ * Connection established.
+ *
+ * @return boolean
+ */
+ public function isConnected()
+ {
+ return ($this->connection && is_resource($this->connection));
+ }
+
+ /**
+ * Close connection.
+ *
+ * @return void
+ */
+ public function disconnect()
+ {
+ if ($this->isConnected()) {
+ @stream_socket_shutdown($this->connection, STREAM_SHUT_RDWR);
+ }
+ $this->connection = null;
+ $this->activeHost = [];
+ }
+
+
+ /**
+ * Write frame to server.
+ *
+ * @param Frame $stompFrame
+ * @return boolean
+ * @throws ConnectionException
+ */
+ public function writeFrame(Frame $stompFrame)
+ {
+ if (!$this->isConnected()) {
+ throw new ConnectionException('Not connected to any server.', $this->activeHost);
+ }
+ $this->writeData($stompFrame, $this->writeTimeout);
+ $this->observers->sentFrame($stompFrame);
+ return true;
+ }
+
+ /**
+ * Write passed data to the stream, respecting passed timeout.
+ *
+ * @param Frame|string $stompFrame
+ * @param float $timeout in seconds, supporting fractions
+ * @throws ConnectionException
+ */
+ private function writeData($stompFrame, $timeout)
+ {
+ $data = (string) $stompFrame;
+ $offset = 0;
+ $size = strlen($data);
+ $lastByteTime = microtime(true);
+ do {
+ $written = @fwrite($this->connection, substr($data, $offset), $this->maxWriteBytes);
+
+ if ($written === false) {
+ throw new ConnectionException('Was not possible to write frame!', $this->activeHost);
+ }
+
+ if ($written > 0) {
+ // offset tracking
+ $offset += $written;
+ $lastByteTime = microtime(true);
+ } else {
+ // timeout tracking
+ if ((microtime(true) - $lastByteTime) > $timeout) {
+ throw new ConnectionException(
+ 'Was not possible to write frame! Write operation timed out.',
+ $this->activeHost
+ );
+ }
+ }
+ // keep some time to breath
+ if ($written < $size) {
+ time_nanosleep(0, 2500000); // 2.5ms / 0.0025s
+ }
+ } while ($offset < $size);
+ }
+
+ /**
+ * Try to read a frame from the server.
+ *
+ * @return Frame|false when no frame to read
+ * @throws ConnectionException
+ * @throws ErrorFrameException
+ */
+ public function readFrame()
+ {
+ // first we try to check the parser for any leftover frames
+ if ($frame = $this->parser->nextFrame()) {
+ return $this->onFrame($frame);
+ }
+
+ if (!$this->hasDataToRead()) {
+ return false;
+ }
+
+ do {
+ $read = @fread($this->connection, $this->maxReadBytes);
+ if ($read === false) {
+ throw new ConnectionException(sprintf('Was not possible to read data from stream.'), $this->activeHost);
+ }
+
+ // this can be caused by different events on the stream, ex. new data or any kind of signal
+ // it also happens when a ssl socket was closed on the other side... so we need to test
+ if ($read === '') {
+ $this->observers->emptyRead();
+ // again we give some time here
+ // as this path is most likely indicating that the socket is not working anymore
+ time_nanosleep(0, 5000000); // 5ms / 0.005s
+ return false;
+ }
+
+ $this->parser->addData($read);
+
+ if ($frame = $this->parser->nextFrame()) {
+ return $this->onFrame($frame);
+ }
+ } while ($this->isDataOnStream());
+
+ return false;
+ }
+
+ /**
+ * The connection onFrame handler.
+ *
+ * @param Frame $frame
+ * @return Frame
+ * @throws ErrorFrameException
+ */
+ private function onFrame(Frame $frame)
+ {
+ if ($frame->isErrorFrame()) {
+ throw new ErrorFrameException($frame);
+ }
+ return $frame;
+ }
+
+ /**
+ * Check if connection has new data which can be read.
+ *
+ * This might wait until readTimeout is reached.
+ *
+ * @return boolean
+ * @throws ConnectionException
+ * @see Connection::setReadTimeout()
+ */
+ public function hasDataToRead()
+ {
+ if (!$this->isConnected()) {
+ throw new ConnectionException('Not connected to any server.', $this->activeHost);
+ }
+
+ $isDataInBuffer = $this->connectionHasDataToRead($this->readTimeout[0], $this->readTimeout[1]);
+ if (!$isDataInBuffer) {
+ $this->observers->emptyBuffer();
+ }
+ return $isDataInBuffer;
+ }
+
+ /**
+ * See if the connection has data left.
+ *
+ * If both timeout-parameters are set to 0, it will return immediately.
+ *
+ * @param int $timeoutSec Second-timeout part
+ * @param int $timeoutMicros Microsecond-timeout part
+ * @return bool
+ * @throws ConnectionException
+ */
+ private function connectionHasDataToRead($timeoutSec, $timeoutMicros)
+ {
+ $timeout = microtime(true) + $timeoutSec + ($timeoutMicros ? $timeoutMicros / 1000000 : 0);
+ while (($hasData = $this->isDataOnStream()) === false) {
+ if ($timeout < microtime(true)) {
+ return false;
+ }
+ if ($this->waitCallback) {
+ if (call_user_func($this->waitCallback) === false) {
+ return false;
+ }
+ }
+
+ $slept = time_nanosleep(0, 2500000); // 2.5ms / 0.0025s
+ if (\is_array($slept)) {
+ return false;
+ }
+ }
+
+ return $hasData === true;
+ }
+
+ /**
+ * Checks if there is readable data on the stream.
+ *
+ * Will return true if data is available, false if no data is detected and null if the operation was interrupted.
+ *
+ * @return bool|null
+ * @throws ConnectionException
+ */
+ private function isDataOnStream()
+ {
+ $read = [$this->connection];
+ $write = null;
+ $except = null;
+ $hasStreamInfo = @stream_select($read, $write, $except, 0);
+
+ if ($hasStreamInfo === false) {
+ // can return `false` if used in combination with `pcntl_signal` and lead to false errors here
+ $error = error_get_last();
+ if ($error && isset($error['message']) && stripos($error['message'], 'interrupted system call') === false) {
+ throw new ConnectionException(
+ 'Check failed to determine if the socket is readable.',
+ $this->activeHost
+ );
+ }
+ return null;
+ }
+
+ return !empty($read);
+ }
+
+ /**
+ * Returns the parser which is used by the connection.
+ *
+ * @return Parser
+ */
+ public function getParser()
+ {
+ return $this->parser;
+ }
+
+ /**
+ * Returns the host the connection was established to.
+ *
+ * @return String
+ */
+ public function getHost()
+ {
+ return $this->host;
+ }
+
+ /**
+ * Writes an "alive" message on the connection to indicate that the client is alive.
+ *
+ * @param float $timeout in seconds supporting fractions (microseconds)
+ *
+ * @return void
+ * @throws ConnectionException
+ */
+ public function sendAlive($timeout = 1.0)
+ {
+ if ($this->isConnected()) {
+ $this->writeData(self::ALIVE, $timeout);
+ }
+ }
+
+ /**
+ * Immediately releases all allocated resources when the connection object gets destroyed.
+ *
+ * This is especially important for long running processes.
+ */
+ public function __destruct()
+ {
+ $this->disconnect();
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network\Observer;
+
+use Stomp\Transport\Frame;
+
+/**
+ * AbstractBeats base for heart beat observer.
+ *
+ * @package Stomp\Network\Observer
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+abstract class AbstractBeats implements ConnectionObserver
+{
+ /**
+ * Frame from client that request a connection.
+ */
+ const FRAME_CLIENT_CONNECT = 'CONNECT';
+
+ /**
+ * Frame from server when a connection is established.
+ */
+ const FRAME_SERVER_CONNECTED = 'CONNECTED';
+ /**
+ * The beat interval that the client wants to use.
+ *
+ * @var integer
+ */
+ protected $intervalClient;
+ /**
+ * The beat interval that the server wants to use.
+ *
+ * @var integer
+ */
+ protected $intervalServer;
+ /**
+ * The timestamp that is known as the last time a beat was detected/issued.
+ *
+ * @var float
+ */
+ private $lastbeat;
+
+ /**
+ * The interval (seconds with microseconds as fraction) that will be used to detect a delay.
+ *
+ * @var float
+ */
+ private $intervalUsed;
+
+ /**
+ * Whenever the emitter is configured to send beats.
+ *
+ * @var bool
+ */
+ private $enabled = false;
+
+ /**
+ * A frame with heartbeat details was detected.
+ *
+ * Child class should set client or server interval property.
+ *
+ * @see $intervalClient
+ * @see $intervalServer
+ *
+ * @param Frame $frame
+ * @param array $beats
+ * @return void
+ */
+ abstract protected function onHeartbeatFrame(Frame $frame, array $beats);
+
+ /**
+ * Called whenever the server send data.
+ *
+ * @return void
+ */
+ abstract protected function onServerActivity();
+
+ /**
+ * Must return the interval (ms) that should be used to detect a delay.
+ *
+ * @param integer $maximum agreement from client and server in milliseconds
+ * @return float
+ */
+ abstract protected function calculateInterval($maximum);
+
+ /**
+ * Called whenever a activity is detected that was issued by the client.
+ *
+ * @return void
+ */
+ abstract protected function onClientActivity();
+
+ /**
+ * Something on the connection state could have changed.
+ *
+ * @return void
+ */
+ abstract protected function onPotentialConnectionStateActivity();
+
+ /**
+ * Delay was detected.
+ *
+ * @return void
+ */
+ abstract protected function onDelay();
+
+ /**
+ * Checks if the emitter was enabled.
+ *
+ * @return bool
+ */
+ public function isEnabled()
+ {
+ return $this->enabled;
+ }
+
+ /**
+ * Returns if the emitter is in a state that indicates a delay.
+ *
+ * @return bool
+ */
+ public function isDelayed()
+ {
+ if ($this->enabled && $this->lastbeat) {
+ $now = microtime(true);
+ return ($now - $this->lastbeat > $this->intervalUsed);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the calculated interval for beats in seconds (with micro fraction).
+ *
+ * @return null|float
+ */
+ public function getInterval()
+ {
+ return $this->intervalUsed;
+ }
+
+ /**
+ * Check if there is a delay and issue follow up tasks if so.
+ *
+ * @return void
+ */
+ protected function checkDelayed()
+ {
+ if ($this->isDelayed()) {
+ $this->onDelay();
+ }
+ }
+
+ /**
+ * Outgoing activity event.
+ *
+ * @return void
+ */
+ protected function rememberActivity()
+ {
+ $this->lastbeat = microtime(true);
+ }
+
+ /**
+ * Returns the heartbeat header.
+ *
+ * @param Frame $frame
+ * @return array
+ */
+ private function getHeartbeats(Frame $frame)
+ {
+ $beats = $frame['heart-beat'];
+ if ($beats) {
+ return explode(',', $beats, 2);
+ }
+ return [0, 0];
+ }
+
+ /**
+ * Enables the delay detection when preconditions are fulfilled.
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ private function enable(Frame $frame)
+ {
+ $this->onHeartbeatFrame($frame, $this->getHeartbeats($frame));
+ if ($this->intervalServer && $this->intervalClient) {
+ $intervalAgreement = $this->calculateInterval(max($this->intervalClient, $this->intervalServer));
+ $this->intervalUsed = $intervalAgreement / 1000; // milli to micro
+ if ($intervalAgreement) {
+ $this->enabled = true;
+ $this->rememberActivity();
+ }
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function receivedFrame(Frame $frame)
+ {
+ if ($this->enabled) {
+ $this->onServerActivity();
+ return;
+ }
+
+ if ($frame->getCommand() === self::FRAME_SERVER_CONNECTED) {
+ $this->enable($frame);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function sentFrame(Frame $frame)
+ {
+ if ($this->enabled) {
+ $this->onClientActivity();
+ return;
+ }
+ if ($frame->getCommand() === self::FRAME_CLIENT_CONNECT) {
+ $this->enable($frame);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function emptyLineReceived()
+ {
+ $this->onServerActivity();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function emptyRead()
+ {
+ $this->onPotentialConnectionStateActivity();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function emptyBuffer()
+ {
+ $this->onServerActivity();
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network\Observer;
+
+use Stomp\Transport\Frame;
+
+/**
+ * Interface ConnectionObserver defines the observable events on a connection.
+ *
+ * @package Stomp\Network\Observer
+ */
+interface ConnectionObserver
+{
+ /**
+ * Indicates that during a read call no frame was received, but an EOL line.
+ *
+ * @return void
+ */
+ public function emptyLineReceived();
+
+ /**
+ * Indicates that the connection has no pending data.
+ *
+ * @return void
+ */
+ public function emptyBuffer();
+
+ /**
+ * Indicates that the connection tried to read signaled data, but no data was returned.
+ *
+ * @return void
+ */
+ public function emptyRead();
+
+ /**
+ * Indicates that a frame has been received from the server.
+ *
+ * @param Frame $frame that has been received
+ * @return void
+ */
+ public function receivedFrame(Frame $frame);
+
+ /**
+ * Indicates that a frame has been sent to the server.
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function sentFrame(Frame $frame);
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network\Observer;
+
+use Stomp\Transport\Frame;
+
+/**
+ * ConnectionObserverCollection a collection of connection observers.
+ *
+ * @package Stomp\Network\Observer
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ConnectionObserverCollection implements ConnectionObserver
+{
+ /**
+ * @var ConnectionObserver[]
+ */
+ private $observers = [];
+
+ /**
+ * Adds new observers to the collection.
+ *
+ * @param ConnectionObserver $observer
+ * @return ConnectionObserverCollection this collection
+ */
+ public function addObserver(ConnectionObserver $observer)
+ {
+ if (!in_array($observer, $this->observers, true)) {
+ $this->observers[] = $observer;
+ }
+ return $this;
+ }
+
+ /**
+ * Removes the observers from the collection.
+ *
+ * @param ConnectionObserver $observer
+ * @return ConnectionObserverCollection this collection
+ */
+ public function removeObserver(ConnectionObserver $observer)
+ {
+ $index = array_search($observer, $this->observers, true);
+ if ($index !== false) {
+ unset($this->observers[$index]);
+ }
+ return $this;
+ }
+
+ /**
+ * Returns the observers inside this collection.
+ *
+ * @return ConnectionObserver[]
+ */
+ public function getObservers()
+ {
+ return array_values($this->observers);
+ }
+
+ /**
+ * Indicates that during a read call no frame was received, but an EOL line.
+ *
+ * @return void
+ */
+ public function emptyLineReceived()
+ {
+ foreach ($this->observers as $item) {
+ $item->emptyLineReceived();
+ }
+ }
+
+ /**
+ * Indicates that a frame has been received.
+ *
+ * @param Frame $frame that has been received
+ * @return void
+ */
+ public function receivedFrame(Frame $frame)
+ {
+ foreach ($this->observers as $item) {
+ $item->receivedFrame($frame);
+ }
+ }
+
+ /**
+ * Indicates that a frame has been transmitted.
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function sentFrame(Frame $frame)
+ {
+ foreach ($this->observers as $item) {
+ $item->sentFrame($frame);
+ }
+ }
+
+ /**
+ * Indicates that the connection has no pending data.
+ *
+ * @return void
+ */
+ public function emptyBuffer()
+ {
+ foreach ($this->observers as $item) {
+ $item->emptyBuffer();
+ }
+ }
+
+ /**
+ * Indicates that the connection tried to read signaled data, but no data was returned.
+ *
+ * @return void
+ */
+ public function emptyRead()
+ {
+ foreach ($this->observers as $item) {
+ $item->emptyRead();
+ }
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network\Observer\Exception;
+
+/**
+ * HeartbeatException indicate that heartbeats where not send or received as expected.
+ *
+ * @package src\Network\Observer\Exception
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class HeartbeatException extends \RuntimeException
+{
+ /**
+ * ClientHeartbeatException constructor.
+ *
+ * @param string $message
+ * @param \Exception|null $previous
+ */
+ public function __construct($message, \Exception $previous = null)
+ {
+ parent::__construct($message, 0, $previous);
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network\Observer;
+
+use Stomp\Exception\ConnectionException;
+use Stomp\Network\Connection;
+use Stomp\Network\Observer\Exception\HeartbeatException;
+use Stomp\Transport\Frame;
+
+/**
+ * HeartbeatEmitter a very basic heartbeat emitter that sends beats from client side.
+ *
+ * Use this if you can guarantee that your client processes workloads within a given interval. This allows the server to
+ * detect that your client is down when it fails sending heartbeats, your client will also fail with exception when the
+ * server is not longer receiving heartbeats.
+ *
+ * If your client needs a unknown runtime to process Messages you should check ServerAliveObserver.
+ *
+ * @example $client->setHeartbeat(2000, 0); // indicate that we would send beats within a 2 second interval
+ * $emitter = new HeartbeatEmitter($client->getConnection());
+ * $client->getConnection()->getObservers()->addObserver($emitter);
+ *
+ * @see ServerAliveObserver
+ * @package Stomp\Network\Observer\Heartbeat
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class HeartbeatEmitter extends AbstractBeats
+{
+ /**
+ * @var Connection
+ */
+ private $connection;
+
+ /**
+ * Defines the percentage amount of the calculated interval that will be used without emitting a beat.
+ *
+ * @var float
+ */
+ private $intervalUsage;
+
+ /**
+ * Enables the pessimistic mode of the emitter, causing alive messages when we receive nothing from the socket.
+ *
+ * @var bool
+ */
+ private $pessimistic = false;
+
+ /**
+ * Emitter constructor.
+ *
+ * What is the interval usage?
+ * The usage (percentage) defines the amount of agreed beat interval time,
+ * that is allowed to pass before the emitter will send a beat.
+ *
+ * A higher value increases the risk that a beat is send after a timeout has occurred.
+ * A lower value increases the beats and adds overhead to the connection.
+ *
+ * @param Connection $connection
+ * @param float $intervalUsage
+ */
+ public function __construct(Connection $connection, $intervalUsage = 0.65)
+ {
+ $this->intervalUsage = max(0.05, min($intervalUsage, 0.95));
+ $this->connection = $connection;
+ }
+
+ /**
+ * Enables the pessimistic mode.
+ *
+ * @param bool $pessimistic
+ */
+ public function setPessimistic($pessimistic)
+ {
+ $this->pessimistic = $pessimistic;
+ }
+
+ /**
+ * Called whenever the server send data.
+ *
+ * @return void
+ */
+ protected function onServerActivity()
+ {
+ $this->checkDelayed();
+ }
+
+ /**
+ * A frame with heartbeat details was detected.
+ *
+ * Class should set client or server interval.
+ *
+ * @param Frame $frame
+ * @param array $beats
+ * @return void
+ */
+ protected function onHeartbeatFrame(Frame $frame, array $beats)
+ {
+ if ($frame->getCommand() === self::FRAME_SERVER_CONNECTED) {
+ $this->intervalServer = $beats[1];
+ if ($this->intervalClient === null) {
+ $this->intervalClient = $this->intervalServer;
+ }
+ } else {
+ $this->intervalClient = $beats[0];
+ $this->rememberActivity();
+ }
+ }
+
+ /**
+ * Must return the interval (ms) that should be used to detect a delay.
+ *
+ * @param integer $maximum
+ * @return float
+ */
+ protected function calculateInterval($maximum)
+ {
+ $intervalUsed = $maximum * $this->intervalUsage;
+ $this->assertReadTimeoutSufficient($intervalUsed);
+ return $intervalUsed;
+ }
+
+ /**
+ * Verify that the client configured heartbeats don't conflict with the connection read timeout.
+ *
+ * @param float $interval
+ * @return void
+ */
+ private function assertReadTimeoutSufficient($interval)
+ {
+ $readTimeout = $this->connection->getReadTimeout();
+ $readTimeoutMs = ($readTimeout[0] * 1000) + ($readTimeout[1] / 1000);
+
+ if ($interval < $readTimeoutMs) {
+ throw new HeartbeatException(
+ 'Client heartbeat is lower than connection read timeout, causing failing heartbeats.'
+ );
+ }
+ }
+
+ /**
+ * Called whenever a activity is detected that was issued by the client.
+ *
+ * @return void
+ */
+ protected function onClientActivity()
+ {
+ $this->rememberActivity();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function onPotentialConnectionStateActivity()
+ {
+ if ($this->pessimistic && $this->isEnabled()) {
+ $this->onDelay();
+ } else {
+ $this->checkDelayed();
+ }
+ }
+
+ /**
+ * Send a beat to the server.
+ *
+ * @return void
+ */
+ protected function onDelay()
+ {
+ try {
+ $this->connection->sendAlive($this->intervalClient / 1000);
+ } catch (ConnectionException $e) {
+ throw new HeartbeatException('Could not send heartbeat to server.', $e);
+ }
+ $this->rememberActivity();
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Network\Observer;
+
+use Stomp\Network\Observer\Exception\HeartbeatException;
+use Stomp\Transport\Frame;
+
+/**
+ * ServerAliveObserver an observer that checks for signals from server side.
+ *
+ * Use this to ensure that the server your listening to is still alive.
+ *
+ * If you want to signal the server that your client is still available check HeartbeatEmitter.
+ *
+ * @example $client->setHeartbeat(0, 2000); // indicate that we would receive server beats within a 2 second interval
+ * $client->getConnection()->getObservers()->addObserver(new ServerAliveObserver());
+ *
+ * @see HeartbeatEmitter
+ * @package Stomp\Network\Observer
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ServerAliveObserver extends AbstractBeats
+{
+ /**
+ * Defines the percentage amount of the calculated interval that will be used without emitting a beat.
+ *
+ * @var float
+ */
+ private $intervalUsage;
+
+ /**
+ * Emitter constructor.
+ *
+ * What is the interval usage?
+ * The usage (percentage) defines the amount of agreed beat interval time,
+ * that is allowed to pass before the observer decides that the server is delayed. (not alive anymore)
+ *
+ * A higher value increases the risk that a dead server is not detected over a given period.
+ * A lower value increases the risk that a server is declared as dead when not.
+ *
+ * @param float $intervalUsage 150% default
+ */
+ public function __construct($intervalUsage = 1.5)
+ {
+ $this->intervalUsage = max(1, $intervalUsage);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function onPotentialConnectionStateActivity()
+ {
+ $this->checkDelayed();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function onServerActivity()
+ {
+ $this->rememberActivity();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function onClientActivity()
+ {
+ // ignored here, as we see failures when the write fails
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function onDelay()
+ {
+ throw new HeartbeatException('The server failed to send expected heartbeats.');
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function onHeartbeatFrame(Frame $frame, array $beats)
+ {
+ if ($frame->getCommand() === self::FRAME_CLIENT_CONNECT) {
+ $this->intervalClient = $beats[1];
+ } else {
+ $this->intervalServer = $beats[0];
+ $this->rememberActivity();
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function calculateInterval($maximum)
+ {
+ return $maximum * $this->intervalUsage;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Protocol;
+
+use Stomp\Exception\StompException;
+use Stomp\Transport\Frame;
+
+/**
+ * Stomp base protocol
+ *
+ *
+ * @package Stomp
+ * @author Hiram Chirino <hiram@hiramchirino.com>
+ * @author Dejan Bosanac <dejan@nighttale.net>
+ * @author Michael Caplan <mcaplan@labnet.net>
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Protocol
+{
+ /**
+ * Client id used for durable subscriptions
+ *
+ * @var string
+ */
+ private $clientId;
+
+ /**
+ * @var string
+ */
+ private $version;
+
+ /**
+ * Server Version
+ *
+ * @var string
+ */
+ private $server;
+
+ /**
+ * Setup stomp protocol with configuration.
+ *
+ * @param string $clientId
+ * @param string $version
+ * @param string $server
+ */
+ public function __construct($clientId, $version = Version::VERSION_1_0, $server = null)
+ {
+ $this->clientId = $clientId;
+ $this->server = $server;
+ $this->version = $version;
+ }
+
+ /**
+ * Get the connect frame
+ *
+ * @param string $login
+ * @param string $passcode
+ * @param array $versions
+ * @param string $host
+ * @param int[] $heartbeat
+ * @return \Stomp\Transport\Frame
+ */
+ final public function getConnectFrame(
+ $login = '',
+ $passcode = '',
+ array $versions = [],
+ $host = null,
+ $heartbeat = [0, 0]
+ ) {
+ $frame = $this->createFrame('CONNECT');
+ $frame->legacyMode(true);
+
+ if ($login || $passcode) {
+ $frame->addHeaders(['login' => $login, 'passcode' => $passcode]);
+ }
+
+ if ($this->hasClientId()) {
+ $frame['client-id'] = $this->getClientId();
+ }
+
+ if (!empty($versions)) {
+ $frame['accept-version'] = implode(',', $versions);
+ }
+
+ $frame['host'] = $host;
+
+ $frame['heart-beat'] = $heartbeat[0] . ',' . $heartbeat[1];
+
+ return $frame;
+ }
+
+ /**
+ * Get subscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param string $ack
+ * @param string $selector
+ * @return \Stomp\Transport\Frame
+ * @throws StompException;
+ */
+ public function getSubscribeFrame($destination, $subscriptionId = null, $ack = 'auto', $selector = null)
+ {
+ // validate ACK types per spec
+ // https://stomp.github.io/stomp-specification-1.0.html#frame-ACK
+ // https://stomp.github.io/stomp-specification-1.1.html#ACK
+ // https://stomp.github.io/stomp-specification-1.2.html#ACK
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $validAcks = ['auto', 'client', 'client-individual'];
+ } else {
+ $validAcks = ['auto', 'client'];
+ }
+ if (!in_array($ack, $validAcks)) {
+ throw new StompException(
+ sprintf(
+ '"%s" is not a valid ack value for STOMP %s. A valid value is one of %s',
+ $ack,
+ $this->version,
+ implode(',', $validAcks)
+ )
+ );
+ }
+
+ $frame = $this->createFrame('SUBSCRIBE');
+
+ $frame['destination'] = $destination;
+ $frame['ack'] = $ack;
+ $frame['id'] = $subscriptionId;
+ $frame['selector'] = $selector;
+ return $frame;
+ }
+
+ /**
+ * Get unsubscribe frame.
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @return \Stomp\Transport\Frame
+ */
+ public function getUnsubscribeFrame($destination, $subscriptionId = null)
+ {
+ $frame = $this->createFrame('UNSUBSCRIBE');
+ $frame['destination'] = $destination;
+ $frame['id'] = $subscriptionId;
+ return $frame;
+ }
+
+ /**
+ * Get transaction begin frame.
+ *
+ * @param string $transactionId
+ * @return \Stomp\Transport\Frame
+ */
+ public function getBeginFrame($transactionId = null)
+ {
+ $frame = $this->createFrame('BEGIN');
+ $frame['transaction'] = $transactionId;
+ return $frame;
+ }
+
+ /**
+ * Get transaction commit frame.
+ *
+ * @param string $transactionId
+ * @return \Stomp\Transport\Frame
+ */
+ public function getCommitFrame($transactionId = null)
+ {
+ $frame = $this->createFrame('COMMIT');
+ $frame['transaction'] = $transactionId;
+ return $frame;
+ }
+
+ /**
+ * Get transaction abort frame.
+ *
+ * @param string $transactionId
+ * @return \Stomp\Transport\Frame
+ */
+ public function getAbortFrame($transactionId = null)
+ {
+ $frame = $this->createFrame('ABORT');
+ $frame['transaction'] = $transactionId;
+ return $frame;
+ }
+
+ /**
+ * Get message acknowledge frame.
+ *
+ * @param Frame $frame
+ * @param string $transactionId
+ * @return Frame
+ */
+ public function getAckFrame(Frame $frame, $transactionId = null)
+ {
+ $ack = $this->createFrame('ACK');
+ $ack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $ack['id'] = $frame->getMessageId();
+ } else {
+ $ack['message-id'] = $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $ack['subscription'] = $frame['subscription'];
+ }
+ }
+ return $ack;
+ }
+
+ /**
+ * Get message not acknowledge frame.
+ *
+ * @param \Stomp\Transport\Frame $frame
+ * @param string $transactionId
+ * @param bool $requeue Requeue header
+ * @return \Stomp\Transport\Frame
+ * @throws StompException
+ * @throws \LogicException
+ */
+ public function getNackFrame(Frame $frame, $transactionId = null, $requeue = null)
+ {
+ if ($requeue !== null) {
+ throw new \LogicException('requeue header not supported');
+ }
+ if ($this->version === Version::VERSION_1_0) {
+ throw new StompException('Stomp Version 1.0 has no support for NACK Frames.');
+ }
+ $nack = $this->createFrame('NACK');
+ $nack['transaction'] = $transactionId;
+ if ($this->hasVersion(Version::VERSION_1_2)) {
+ $nack['id'] = $frame->getMessageId();
+ } else {
+ $nack['message-id'] = $frame->getMessageId();
+ if ($this->hasVersion(Version::VERSION_1_1)) {
+ $nack['subscription'] = $frame['subscription'];
+ }
+ }
+
+ $nack['message-id'] = $frame->getMessageId();
+ return $nack;
+ }
+
+ /**
+ * Get the disconnect frame.
+ *
+ * @return \Stomp\Transport\Frame
+ */
+ public function getDisconnectFrame()
+ {
+ $frame = $this->createFrame('DISCONNECT');
+ if ($this->hasClientId()) {
+ $frame['client-id'] = $this->getClientId();
+ }
+ return $frame;
+ }
+
+ /**
+ * Client Id is set
+ *
+ * @return boolean
+ */
+ public function hasClientId()
+ {
+ return (boolean) $this->clientId;
+ }
+
+ /**
+ * Client Id is set
+ *
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->clientId;
+ }
+
+ /**
+ * Stomp Version
+ *
+ * @return string
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Server Version Info
+ *
+ * @return string
+ */
+ public function getServer()
+ {
+ return $this->server;
+ }
+
+ /**
+ * Checks if given version is included (equal or lower) in active protocol version.
+ *
+ * @param string $version
+ * @return bool
+ */
+ public function hasVersion($version)
+ {
+ return version_compare($this->version, $version, '>=');
+ }
+
+ /**
+ * Creates a Frame according to the detected STOMP version.
+ *
+ * @param string $command
+ * @return Frame
+ */
+ protected function createFrame($command)
+ {
+ $frame = new Frame($command);
+
+ if ($this->version === Version::VERSION_1_0) {
+ $frame->legacyMode(true);
+ }
+
+ return $frame;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Protocol;
+
+use Stomp\Broker\ActiveMq\ActiveMq;
+use Stomp\Broker\Apollo\Apollo;
+use Stomp\Broker\RabbitMq\RabbitMq;
+use Stomp\Broker\OpenMq\OpenMq;
+use Stomp\Exception\StompException;
+use Stomp\Exception\UnexpectedResponseException;
+use Stomp\Transport\Frame;
+
+/**
+ * Version determine stomp version and server dialect.
+ *
+ * @package Stomp\Protocol
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Version
+{
+ /**
+ * Stomp Version 1.0
+ */
+ const VERSION_1_0 = '1.0';
+ /**
+ * Stomp Version 1.1
+ */
+ const VERSION_1_1 = '1.1';
+ /**
+ * Stomp Version 1.2
+ */
+ const VERSION_1_2 = '1.2';
+
+ /**
+ * @var Frame
+ */
+ private $frame;
+
+
+ /**
+ * Version constructor.
+ *
+ * @param Frame $frame
+ * @throws StompException
+ */
+ public function __construct(Frame $frame)
+ {
+ if ($frame->getCommand() != 'CONNECTED') {
+ throw new UnexpectedResponseException(
+ $frame,
+ sprintf('Expected a "CONNECTED" Frame to determine Version. Got a "%s" Frame!', $frame->getCommand())
+ );
+ }
+ $this->frame = $frame;
+ }
+
+ /**
+ * Returns the protocol to use.
+ *
+ * @param string $clientId
+ * @param string $default server to use of no server detected
+ * @return ActiveMq|Apollo|Protocol|RabbitMq
+ */
+ public function getProtocol($clientId, $default = 'ActiveMQ/5.11.1')
+ {
+ $server = trim($this->frame['server']) ?: $default;
+ $version = $this->getVersion();
+ if (stristr($server, 'rabbitmq') !== false) {
+ return new RabbitMq($clientId, $version, $server);
+ }
+ if (stristr($server, 'apache-apollo') !== false) {
+ return new Apollo($clientId, $version, $server);
+ }
+ if (stristr($server, 'activemq') !== false) {
+ return new ActiveMq($clientId, $version, $server);
+ }
+ if (stristr($server, 'open message queue') !== false) {
+ return new OpenMq($clientId, $version, $server);
+ }
+ return new Protocol($clientId, $version, $server);
+ }
+
+ /**
+ * Detected version
+ *
+ * @return string
+ */
+ public function getVersion()
+ {
+ return $this->frame['version'] ?: self::VERSION_1_0;
+ }
+
+ /**
+ * Check if version is same or newer than given one.
+ *
+ * @param string $version to check against
+ * @return boolean
+ */
+ public function hasVersion($version)
+ {
+ return version_compare($this->getVersion(), $version, '>=');
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp;
+
+use Stomp\Exception\StompException;
+use Stomp\Protocol\Protocol;
+use Stomp\Transport\Frame;
+use Stomp\Transport\Message;
+
+/**
+ * Simple Stomp Client
+ *
+ * This is a legacy implementation of the old Stomp Client (Version 2-3).
+ * It's an almost stateless client, only wrapping some protocol calls for you.
+ *
+ * @package Stomp
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class SimpleStomp
+{
+ /**
+ * @var Client
+ */
+ protected $client;
+
+ /**
+ * LegacyStomp constructor.
+ *
+ * @param Client $client
+ */
+ public function __construct(Client $client)
+ {
+ $this->client = $client;
+ }
+
+ /**
+ * Read response frame from server
+ *
+ * @return Frame|false when no frame to read
+ */
+ public function read()
+ {
+ return $this->client->readFrame();
+ }
+
+ /**
+ * Register to listen to a given destination
+ *
+ * @param string $destination Destination queue
+ * @param null $subscriptionId
+ * @param string $ack
+ * @param string $selector
+ * @param array $header
+ * @return bool
+ */
+ public function subscribe($destination, $subscriptionId = null, $ack = 'auto', $selector = null, array $header = [])
+ {
+ return $this->client->sendFrame(
+ $this->getProtocol()->getSubscribeFrame($destination, $subscriptionId, $ack, $selector)->addHeaders($header)
+ );
+ }
+
+ /**
+ * @return Protocol
+ */
+ protected function getProtocol()
+ {
+ return $this->client->getProtocol();
+ }
+
+ /**
+ * Send a message
+ *
+ * @param string $destination
+ * @param Message $message
+ * @return bool
+ * @throws StompException
+ */
+ public function send($destination, Message $message)
+ {
+ return $this->client->send($destination, $message);
+ }
+
+ /**
+ * Remove an existing subscription
+ *
+ * @param string $destination
+ * @param string $subscriptionId
+ * @param array $header
+ * @return boolean
+ * @throws StompException
+ */
+ public function unsubscribe($destination, $subscriptionId = null, array $header = [])
+ {
+ return $this->client->sendFrame(
+ $this->getProtocol()->getUnsubscribeFrame($destination, $subscriptionId)->addHeaders($header)
+ );
+ }
+
+ /**
+ * Start a transaction
+ *
+ * @param string $transactionId
+ * @return boolean
+ * @throws StompException
+ */
+ public function begin($transactionId = null)
+ {
+ return $this->client->sendFrame($this->getProtocol()->getBeginFrame($transactionId));
+ }
+
+ /**
+ * Commit a transaction in progress
+ *
+ * @param string $transactionId
+ * @return boolean
+ * @throws StompException
+ */
+ public function commit($transactionId = null)
+ {
+ return $this->client->sendFrame($this->getProtocol()->getCommitFrame($transactionId));
+ }
+
+ /**
+ * Roll back a transaction in progress
+ *
+ * @param string $transactionId
+ * @return bool
+ */
+ public function abort($transactionId = null)
+ {
+ return $this->client->sendFrame($this->getProtocol()->getAbortFrame($transactionId));
+ }
+
+ /**
+ * Acknowledge consumption of a message from a subscription
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function ack(Frame $frame)
+ {
+ $this->client->sendFrame($this->getProtocol()->getAckFrame($frame), false);
+ }
+
+ /**
+ * Not acknowledge consumption of a message from a subscription
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function nack(Frame $frame)
+ {
+ $this->client->sendFrame($this->getProtocol()->getNackFrame($frame), false);
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp;
+
+use Stomp\States\IStateful;
+use Stomp\States\Meta\SubscriptionList;
+use Stomp\States\ProducerState;
+use Stomp\States\StateSetter;
+use Stomp\Transport\Frame;
+use Stomp\Transport\Message;
+
+/**
+ * Stateful Stomp Client
+ *
+ * This is a stateful implementation of a stomp client.
+ * This client will help you using stomp in a safe way by using the state machine pattern.
+ *
+ * @package Stomp
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class StatefulStomp extends StateSetter implements IStateful
+{
+
+ /**
+ * active state
+ *
+ * @var IStateful
+ */
+ private $state;
+
+ /**
+ * @var Client
+ */
+ private $client;
+
+ /**
+ * StatefulStomp constructor.
+ *
+ * @param Client $client
+ */
+ public function __construct(Client $client)
+ {
+ $this->client = $client;
+ $this->state = new ProducerState($client, $this);
+ }
+
+ /**
+ * Acknowledge consumption of a message from a subscription
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function ack(Frame $frame)
+ {
+ $this->state->ack($frame);
+ }
+
+ /**
+ * Not acknowledge consumption of a message from a subscription
+ *
+ * @param Frame $frame
+ * @param bool $requeue requeue header not supported in all brokers
+ * @return void
+ */
+ public function nack(Frame $frame, $requeue = null)
+ {
+ $this->state->nack($frame, $requeue);
+ }
+
+ /**
+ * Send a message.
+ *
+ * @param string $destination
+ * @param \Stomp\Transport\Message $message
+ * @return bool
+ */
+ public function send($destination, Message $message)
+ {
+ return $this->state->send($destination, $message);
+ }
+
+ /**
+ * Begins an transaction.
+ *
+ * @return void
+ */
+ public function begin()
+ {
+ $this->state->begin();
+ }
+
+ /**
+ * Commit current transaction.
+ *
+ * @return void
+ */
+ public function commit()
+ {
+ $this->state->commit();
+ }
+
+ /**
+ * Abort current transaction.
+ *
+ * @return void
+ */
+ public function abort()
+ {
+ $this->state->abort();
+ }
+
+ /**
+ * Subscribe to given destination.
+ *
+ * Returns the subscriptionId used for this.
+ *
+ * @param string $destination
+ * @param string $selector
+ * @param string $ack
+ * @param array $header
+ * @return int
+ */
+ public function subscribe($destination, $selector = null, $ack = 'auto', array $header = [])
+ {
+ return $this->state->subscribe($destination, $selector, $ack, $header);
+ }
+
+ /**
+ * Unsubscribe from current or given destination.
+ *
+ * @param int $subscriptionId
+ * @return void
+ */
+ public function unsubscribe($subscriptionId = null)
+ {
+ $this->state->unsubscribe($subscriptionId);
+ }
+
+ /**
+ * Returns as list of all active subscriptions.
+ *
+ * @return SubscriptionList
+ */
+ public function getSubscriptions()
+ {
+ return $this->state->getSubscriptions();
+ }
+
+
+ /**
+ * Read a frame
+ *
+ * @return \Stomp\Transport\Frame|false
+ */
+ public function read()
+ {
+ return $this->state->read();
+ }
+
+ /**
+ * Current State
+ *
+ * @return IStateful
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ /**
+ * Changes the current state.
+ *
+ * @param IStateful $state
+ * @return mixed
+ */
+ protected function setState(IStateful $state)
+ {
+ $this->state = $state;
+ }
+
+ /**
+ * Returns the used client.
+ *
+ * @return Client
+ */
+ public function getClient()
+ {
+ return $this->client;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+use InvalidArgumentException;
+use Stomp\States\Meta\Subscription;
+use Stomp\States\Meta\SubscriptionList;
+use Stomp\Transport\Frame;
+use Stomp\Transport\Message;
+use Stomp\Util\IdGenerator;
+
+/**
+ * ConsumerState client acts as a consumer.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ConsumerState extends StateTemplate
+{
+ /**
+ * Subscription ack mode
+ *
+ * @var string
+ */
+ protected $ack;
+ /**
+ * Subscription selector
+ *
+ * @var string
+ */
+ protected $selector;
+ /**
+ * Subscription target
+ *
+ * @var string
+ */
+ protected $destination;
+
+ /**
+ * SubscriptionId
+ * @var int
+ */
+ protected $subId;
+
+ /**
+ * @var SubscriptionList
+ */
+ protected $subscriptions;
+
+ /**
+ * @inheritdoc
+ */
+ protected function init(array $options = [])
+ {
+ $this->subscriptions = new SubscriptionList();
+ if (isset($options['subscriptions'])) {
+ $this->subscriptions = $options['subscriptions'];
+ } else {
+ $this->subscribe($options['destination'], $options['selector'], $options['ack'], $options['header']);
+ }
+ return $this->subscriptions->getLast()->getSubscriptionId();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function ack(Frame $frame)
+ {
+ $this->getClient()->sendFrame($this->getProtocol()->getAckFrame($frame), false);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function nack(Frame $frame, $requeue = null)
+ {
+ $this->getClient()->sendFrame($this->getProtocol()->getNackFrame($frame, null, $requeue), false);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function send($destination, Message $message)
+ {
+ return $this->getClient()->send($destination, $message);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function begin()
+ {
+ $this->setState(new ConsumerTransactionState($this->getClient(), $this->getBase()), $this->getOptions());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function subscribe($destination, $selector, $ack, array $header = [])
+ {
+ $subscription = new Subscription($destination, $selector, $ack, IdGenerator::generateId(), $header);
+ $this->getClient()->sendFrame(
+ $this->getProtocol()->getSubscribeFrame(
+ $subscription->getDestination(),
+ $subscription->getSubscriptionId(),
+ $subscription->getAck(),
+ $subscription->getSelector()
+ )->addHeaders($header)
+ );
+ $this->subscriptions[$subscription->getSubscriptionId()] = $subscription;
+ return $subscription->getSubscriptionId();
+ }
+
+
+ /**
+ * @inheritdoc
+ */
+ public function unsubscribe($subscriptionId = null)
+ {
+ if ($this->endSubscription($subscriptionId)) {
+ $this->setState(
+ new ProducerState($this->getClient(), $this->getBase())
+ );
+ }
+ }
+
+
+ /**
+ * Closes given subscription or last opened.
+ *
+ * @param string $subscriptionId
+ * @return bool true if last one was closed
+ */
+ protected function endSubscription($subscriptionId = null)
+ {
+ if (!$subscriptionId) {
+ $subscriptionId = $this->subscriptions->getLast()->getSubscriptionId();
+ }
+ if (!isset($this->subscriptions[$subscriptionId])) {
+ throw new InvalidArgumentException(sprintf('%s is no active subscription!', $subscriptionId));
+ }
+ $subscription = $this->subscriptions[$subscriptionId];
+ $this->getClient()->sendFrame(
+ $this->getProtocol()->getUnsubscribeFrame(
+ $subscription->getDestination(),
+ $subscription->getSubscriptionId()
+ )
+ );
+ IdGenerator::releaseId($subscription->getSubscriptionId());
+
+ unset($this->subscriptions[$subscription->getSubscriptionId()]);
+
+ if ($this->subscriptions->count() == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function read()
+ {
+ return $this->getClient()->readFrame();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getSubscriptions()
+ {
+ return $this->subscriptions;
+ }
+
+
+ /**
+ * @inheritdoc
+ */
+ protected function getOptions()
+ {
+ return [
+ 'subscriptions' => $this->subscriptions
+ ];
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+use Stomp\States\Exception\InvalidStateException;
+use Stomp\Transport\Frame;
+
+/**
+ * ConsumerTransactionState client is a consumer within an transaction.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ConsumerTransactionState extends ConsumerState
+{
+ use TransactionsTrait;
+
+ /**
+ * @inheritdoc
+ */
+ protected function init(array $options = [])
+ {
+ $this->initTransaction($options);
+ return parent::init($options);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function commit()
+ {
+ $this->getClient()->sendFrame(
+ $this->getProtocol()->getCommitFrame($this->transactionId)
+ );
+ $this->setState(new ConsumerState($this->getClient(), $this->getBase()), parent::getOptions());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function abort()
+ {
+ $this->transactionAbort();
+ $this->setState(new ConsumerState($this->getClient(), $this->getBase()), parent::getOptions());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function ack(Frame $frame)
+ {
+ $this->getClient()->sendFrame($this->getProtocol()->getAckFrame($frame, $this->transactionId), false);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function nack(Frame $frame, $requeue = null)
+ {
+ $this->getClient()->sendFrame(
+ $this->getProtocol()->getNackFrame($frame, $this->transactionId, $requeue),
+ false
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function unsubscribe($subscriptionId = null)
+ {
+ if ($this->endSubscription($subscriptionId)) {
+ $this->setState(
+ new ProducerTransactionState($this->getClient(), $this->getBase()),
+ ['transactionId' => $this->transactionId]
+ );
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function begin()
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States\Exception;
+
+use Stomp\Exception\StompException;
+use Stomp\States\IStateful;
+
+/**
+ * InvalidStateException indicates that an call to an operation is not possible in current state.
+ *
+ * @package Stomp\States\Exception
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class InvalidStateException extends StompException
+{
+
+ /**
+ * InvalidStateException constructor.
+ *
+ * @param IStateful $state
+ * @param string $method
+ */
+ public function __construct(IStateful $state, $method)
+ {
+ parent::__construct(sprintf('"%s" is not allowed in "%s".', $method, get_class($state)));
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+use Stomp\States\Meta\SubscriptionList;
+use Stomp\Transport\Frame;
+use Stomp\Transport\Message;
+
+/**
+ * Interface IStateful methods that must be treated in every stomp state.
+ *
+ * @package Stomp\States
+ */
+interface IStateful
+{
+ /**
+ * Acknowledge consumption of a message from a subscription
+ *
+ * @param Frame $frame
+ * @return void
+ */
+ public function ack(Frame $frame);
+
+ /**
+ * Not acknowledge consumption of a message from a subscription
+ *
+ * @param Frame $frame
+ * @param bool $requeue Requeue header not supported on all brokers
+ * @return void
+ */
+ public function nack(Frame $frame, $requeue = null);
+
+ /**
+ * Send a message.
+ *
+ * @param string $destination
+ * @param \Stomp\Transport\Message $message
+ * @return bool
+ */
+ public function send($destination, Message $message);
+
+ /**
+ * Begins an transaction.
+ *
+ * @return void
+ */
+ public function begin();
+
+ /**
+ * Commit current transaction.
+ *
+ * @return void
+ */
+ public function commit();
+
+ /**
+ * Abort current transaction.
+ *
+ * @return void
+ */
+ public function abort();
+
+ /**
+ * Subscribe to given destination.
+ *
+ * Returns the subscriptionId used for this.
+ *
+ * @param string $destination
+ * @param string $selector
+ * @param string $ack
+ * @param array $header
+ * @return int
+ */
+ public function subscribe($destination, $selector, $ack, array $header = []);
+
+ /**
+ * Unsubscribe from current or given destination.
+ *
+ * @param int $subscriptionId
+ * @return void
+ */
+ public function unsubscribe($subscriptionId = null);
+
+
+ /**
+ * Read a frame
+ *
+ * @return \Stomp\Transport\Frame|false
+ */
+ public function read();
+
+ /**
+ * Returns as list of all active subscriptions.
+ *
+ * @return SubscriptionList
+ */
+ public function getSubscriptions();
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States\Meta;
+
+use Stomp\Transport\Frame;
+
+/**
+ * Subscription Meta info
+ *
+ * @package Stomp\States\Meta
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Subscription
+{
+ /**
+ * @var int
+ */
+ private $subscriptionId;
+
+ /**
+ * @var String
+ */
+ private $selector;
+
+ /**
+ * @var String
+ */
+ private $destination;
+
+ /**
+ * @var String
+ */
+ private $ack;
+
+ /**
+ * @var array
+ */
+ private $header;
+
+ /**
+ * Subscription constructor.
+ * @param String $destination
+ * @param String $selector
+ * @param String $ack
+ * @param int $subscriptionId
+ * @param array $header additionally passed to create this subscription
+ */
+ public function __construct($destination, $selector, $ack, $subscriptionId, array $header = [])
+ {
+ $this->subscriptionId = $subscriptionId;
+ $this->selector = $selector;
+ $this->destination = $destination;
+ $this->ack = $ack;
+ $this->header = $header;
+ }
+
+
+ /**
+ * @return int
+ */
+ public function getSubscriptionId()
+ {
+ return $this->subscriptionId;
+ }
+
+ /**
+ * @return String
+ */
+ public function getSelector()
+ {
+ return $this->selector;
+ }
+
+ /**
+ * @return String
+ */
+ public function getDestination()
+ {
+ return $this->destination;
+ }
+
+ /**
+ * @return String
+ */
+ public function getAck()
+ {
+ return $this->ack;
+ }
+
+ /**
+ * @return array
+ */
+ public function getHeader()
+ {
+ return $this->header;
+ }
+
+ /**
+ * Checks if the given frame belongs to current Subscription.
+ *
+ * @param Frame $frame
+ * @return bool
+ */
+ public function belongsTo(Frame $frame)
+ {
+ return ($frame['subscription'] == $this->subscriptionId);
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States\Meta;
+
+use ArrayAccess;
+use ArrayIterator;
+use Countable;
+use IteratorAggregate;
+use Stomp\Transport\Frame;
+
+/**
+ * SubscriptionList meta info for active subscriptions.
+ *
+ * @package Stomp\States\Meta
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class SubscriptionList implements IteratorAggregate, ArrayAccess, Countable
+{
+
+ /**
+ * @var Subscription[]
+ */
+ private $subscriptions = [];
+
+ /**
+ * Returns the last added active Subscription.
+ *
+ * @return Subscription
+ */
+ public function getLast()
+ {
+ return end($this->subscriptions);
+ }
+
+ /**
+ * Returns the subscription the frame belongs to or false if no matching subscription was found.
+ *
+ * @param Frame $frame
+ * @return Subscription|false
+ */
+ public function getSubscription(Frame $frame)
+ {
+ foreach ($this->subscriptions as $subscription) {
+ if ($subscription->belongsTo($frame)) {
+ return $subscription;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->subscriptions);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->subscriptions[$offset]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetGet($offset)
+ {
+ return $this->subscriptions[$offset];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->subscriptions[$offset] = $value;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->subscriptions[$offset]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function count()
+ {
+ return count($this->subscriptions);
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+/**
+ * ProducerState client is working as a message producer.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ProducerState extends StateTemplate
+{
+ /**
+ * @inheritdoc
+ */
+ protected function init(array $options = [])
+ {
+ // nothing to do here
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function begin()
+ {
+ $this->setState(new ProducerTransactionState($this->getClient(), $this->getBase()));
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function subscribe($destination, $selector, $ack, array $header = [])
+ {
+ return $this->setState(
+ new ConsumerState($this->getClient(), $this->getBase()),
+ ['destination' => $destination, 'selector' => $selector, 'ack' => $ack, 'header' => $header]
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getOptions()
+ {
+ return [];
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+use Stomp\States\Exception\InvalidStateException;
+
+/**
+ * ProducerTransactionState client is working in an transaction scope as a message producer.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class ProducerTransactionState extends ProducerState
+{
+ use TransactionsTrait;
+
+ /**
+ * @inheritdoc
+ */
+ protected function init(array $options = [])
+ {
+ $this->initTransaction($options);
+ parent::init($options);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function commit()
+ {
+ $this->transactionCommit();
+ $this->setState(new ProducerState($this->getClient(), $this->getBase()), parent::getOptions());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function abort()
+ {
+ $this->transactionAbort();
+ $this->setState(new ProducerState($this->getClient(), $this->getBase()), parent::getOptions());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function subscribe($destination, $selector, $ack, array $header = [])
+ {
+ return $this->setState(
+ new ConsumerTransactionState($this->getClient(), $this->getBase()),
+ $this->getOptions() +
+ [
+ 'destination' => $destination,
+ 'selector' => $selector,
+ 'ack' => $ack,
+ 'header' => $header
+ ]
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function begin()
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+/**
+ * StateSetter allows to change a state.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+abstract class StateSetter
+{
+ /**
+ * Change current state to given one, might return creation data from state.
+ *
+ * @param IStateful $state
+ * @return mixed
+ */
+ abstract protected function setState(IStateful $state);
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+use Stomp\Client;
+use Stomp\Protocol\Protocol;
+use Stomp\StatefulStomp;
+use Stomp\States\Exception\InvalidStateException;
+use Stomp\States\Meta\SubscriptionList;
+use Stomp\Transport\Frame;
+use Stomp\Transport\Message;
+
+/**
+ * StateTemplate for StompStates.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+abstract class StateTemplate extends StateSetter implements IStateful
+{
+ /**
+ * @var Client
+ */
+ private $client;
+
+ /**
+ * StateMachine
+ *
+ * @var StatefulStomp
+ */
+ private $base;
+
+ /**
+ * StateTemplate constructor.
+ * @param Client $client
+ * @param StatefulStomp $base
+ */
+ public function __construct(Client $client, StatefulStomp $base)
+ {
+ $this->client = $client;
+ $this->base = $base;
+ }
+
+ /**
+ * Returns the base StateMachine.
+ *
+ * @return StatefulStomp
+ */
+ protected function getBase()
+ {
+ return $this->base;
+ }
+
+ /**
+ * Activates the current state, after it has been applied on base.
+ *
+ * @param array $options
+ * @return mixed
+ */
+ abstract protected function init(array $options = []);
+
+ /**
+ * Returns the options needed in current state.
+ *
+ * @return array
+ */
+ abstract protected function getOptions();
+
+ /**
+ * @return Client
+ */
+ protected function getClient()
+ {
+ return $this->client;
+ }
+
+ /**
+ * @return Protocol
+ */
+ protected function getProtocol()
+ {
+ return $this->client->getProtocol();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function setState(IStateful $state, array $options = [])
+ {
+ $init = null;
+ if ($state instanceof StateTemplate) {
+ $init = $state->init($options);
+ }
+ $this->base->setState($state);
+ return $init;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function ack(Frame $frame)
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function nack(Frame $frame, $requeue = null)
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function send($destination, Message $message)
+ {
+ return $this->getClient()->send($destination, $message);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function begin()
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function commit()
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function abort()
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function subscribe($destination, $selector, $ack, array $header = [])
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function unsubscribe($subscriptionId = null)
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function read()
+ {
+ throw new InvalidStateException($this, __FUNCTION__);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getSubscriptions()
+ {
+ return new SubscriptionList();
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\States;
+
+use Stomp\Client;
+use Stomp\Protocol\Protocol;
+use Stomp\Transport\Message;
+use Stomp\Util\IdGenerator;
+
+/**
+ * TransactionsTrait provides base logic for all transaction based states.
+ *
+ * @package Stomp\States
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+trait TransactionsTrait
+{
+
+ /**
+ * @return Protocol
+ */
+ abstract public function getProtocol();
+
+
+ /**
+ * @return Client
+ */
+ abstract public function getClient();
+
+ /**
+ * Id used for current transaction.
+ *
+ * @var int|string
+ */
+ protected $transactionId;
+
+ /**
+ * Init the transaction state.
+ *
+ * @param array $options
+ */
+ protected function initTransaction(array $options = [])
+ {
+ if (!isset($options['transactionId'])) {
+ $this->transactionId = IdGenerator::generateId();
+ $this->getClient()->sendFrame(
+ $this->getProtocol()->getBeginFrame($this->transactionId)
+ );
+ } else {
+ $this->transactionId = $options['transactionId'];
+ }
+ }
+
+ /**
+ * Options for this transaction state.
+ *
+ * @return array
+ */
+ protected function getOptions()
+ {
+ return ['transactionId' => $this->transactionId];
+ }
+
+ /**
+ * Send a message within this transaction.
+ *
+ * @param string $destination
+ * @param \Stomp\Transport\Message $message
+ * @return bool
+ */
+ public function send($destination, Message $message)
+ {
+ return $this->getClient()->send($destination, $message, ['transaction' => $this->transactionId], false);
+ }
+
+ /**
+ * Commit current transaction.
+ */
+ protected function transactionCommit()
+ {
+ $this->getClient()->sendFrame($this->getProtocol()->getCommitFrame($this->transactionId));
+ IdGenerator::releaseId($this->transactionId);
+ }
+
+ /**
+ * Abort the current transaction.
+ */
+ protected function transactionAbort()
+ {
+ $this->getClient()->sendFrame($this->getProtocol()->getAbortFrame($this->transactionId));
+ IdGenerator::releaseId($this->transactionId);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Transport;
+
+/**
+ * Message that contains a stream of uninterpreted bytes
+ *
+ * @package Stomp
+ */
+class Bytes extends Message
+{
+ /**
+ * Constructor
+ *
+ * @param string $body
+ * @param array $headers
+ */
+ public function __construct($body, array $headers = [])
+ {
+ parent::__construct($body, $headers);
+ $this->headers['content-type'] = 'application/octet-stream';
+ $this->expectLengthHeader(true);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getBodySize()
+ {
+ return count(unpack('c*', $this->getBody()));
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Transport;
+
+use ArrayAccess;
+
+/**
+ * Stomp Frames are messages that are sent and received on a stomp connection.
+ *
+ * @package Stomp
+ */
+class Frame implements ArrayAccess
+{
+ /**
+ * Stomp Command
+ *
+ * @var string
+ */
+ protected $command;
+
+ /**
+ * Frame Headers
+ *
+ * @var array
+ */
+ protected $headers;
+
+ /**
+ * Frame Content
+ *
+ * @var mixed
+ */
+ public $body;
+
+ /**
+ * Frame should set an content-length header on transmission
+ *
+ * @var bool
+ */
+ private $addLengthHeader = false;
+
+ /**
+ * Frame is in stomp 1.0 mode
+ *
+ * @var bool
+ */
+ private $legacyMode = false;
+
+ /**
+ * Constructor
+ *
+ * @param string $command
+ * @param array $headers
+ * @param string $body
+ */
+ public function __construct($command = null, array $headers = [], $body = null)
+ {
+ $this->command = $command;
+ $this->headers = $headers ?: [];
+ $this->body = $body;
+ }
+
+ /**
+ * Add given headers to currently set headers.
+ *
+ * Will override existing keys.
+ *
+ * @param array $header
+ * @return Frame
+ */
+ public function addHeaders(array $header)
+ {
+ $this->headers += $header;
+ return $this;
+ }
+
+ /**
+ * Stomp message Id
+ *
+ * @return string
+ */
+ public function getMessageId()
+ {
+ return $this['message-id'];
+ }
+
+ /**
+ * Is error frame.
+ *
+ * @return boolean
+ */
+ public function isErrorFrame()
+ {
+ return ($this->command == 'ERROR');
+ }
+
+ /**
+ * Tell the frame that we expect an length header.
+ *
+ * @param bool|false $expected
+ */
+ public function expectLengthHeader($expected = false)
+ {
+ $this->addLengthHeader = $expected;
+ }
+
+ /**
+ * Enable legacy mode for this frame
+ *
+ * @param bool|false $legacy
+ */
+ public function legacyMode($legacy = false)
+ {
+ $this->legacyMode = $legacy;
+ }
+
+ /**
+ * Frame is in legacy mode.
+ *
+ * @return bool
+ */
+ public function isLegacyMode()
+ {
+ return $this->legacyMode;
+ }
+
+ /**
+ * Command
+ *
+ * @return string
+ */
+ public function getCommand()
+ {
+ return $this->command;
+ }
+
+ /**
+ * Body
+ *
+ * @return string
+ */
+ public function getBody()
+ {
+ return $this->body;
+ }
+
+ /**
+ * Headers
+ *
+ * @return array
+ */
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ /**
+ * Convert frame to transportable string
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $data = $this->command . "\n";
+
+ if (!$this->legacyMode) {
+ if ($this->body && ($this->addLengthHeader || stripos($this->body, "\x00") !== false)) {
+ $this['content-length'] = $this->getBodySize();
+ }
+ }
+
+ foreach ($this->headers as $name => $value) {
+ $data .= $this->encodeHeaderValue($name) . ':' . $this->encodeHeaderValue($value) . "\n";
+ }
+
+ $data .= "\n";
+ $data .= $this->body;
+ return $data . "\x00";
+ }
+
+ /**
+ * Size of Frame body.
+ *
+ * @return int
+ */
+ protected function getBodySize()
+ {
+ return strlen($this->body);
+ }
+
+ /**
+ * Encodes header values.
+ *
+ * @param string $value
+ * @return string
+ */
+ protected function encodeHeaderValue($value)
+ {
+ if ($this->legacyMode) {
+ return str_replace(["\n"], ['\n'], $value);
+ }
+ return str_replace(["\\", "\r", "\n", ':'], ["\\\\", '\r', '\n', '\c'], $value);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->headers[$offset]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetGet($offset)
+ {
+ if (isset($this->headers[$offset])) {
+ return $this->headers[$offset];
+ }
+ return null;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetSet($offset, $value)
+ {
+ if ($value !== null) {
+ $this->headers[$offset] = $value;
+ }
+ }
+
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->headers[$offset]);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Transport;
+
+/**
+ * FrameFactory defines how new frames are created after the frame details have been extracted.
+ *
+ * @package Stomp\Transport
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class FrameFactory
+{
+ /**
+ * @var callable[]
+ */
+ private $resolver = [];
+
+ /**
+ * FrameFactory constructor.
+ */
+ public function __construct()
+ {
+ // register default additional builtin resolvers
+ $this->resolver[] =
+ function ($command, array $headers, $body) {
+ if (isset($headers['transformation']) && strcasecmp($headers['transformation'], 'jms-map-json') == 0) {
+ return new Map($body, $headers, $command);
+ }
+ };
+ }
+
+
+ /**
+ * Creates a frame instance out of the given frame details.
+ *
+ * @param string $command
+ * @param array $headers
+ * @param string $body
+ * @param boolean $legacyMode stomp 1.0 mode (headers)
+ * @return Frame
+ */
+ public function createFrame($command, array $headers, $body, $legacyMode)
+ {
+ foreach ($this->resolver as $resolver) {
+ if ($frame = $resolver($command, $headers, $body, $legacyMode)) {
+ return $frame;
+ }
+ }
+ return $this->defaultFrame($command, $headers, $body, $legacyMode);
+ }
+
+ /**
+ * Creates a new default frame instance.
+ *
+ * @param string $command
+ * @param array $headers
+ * @param string $body
+ * @param boolean $legacyMode
+ * @return Frame
+ */
+ private function defaultFrame($command, array $headers, $body, $legacyMode)
+ {
+ $frame = new Frame($command, $headers, $body);
+ $frame->legacyMode($legacyMode);
+ return $frame;
+ }
+
+ /**
+ * Register a new resolver inside this frame factory.
+ *
+ * The new resolver becomes the first one which will be used to handle the frame create request.
+ * The resolver must return null/false if he won't create a frame for the request.
+ *
+ * @param callable $callable
+ * @return FrameFactory
+ */
+ public function registerResolver($callable)
+ {
+ array_unshift($this->resolver, $callable);
+ return $this;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Transport;
+
+/**
+ * Message that contains a set of name-value pairs
+ *
+ * @package Stomp
+ */
+class Map extends Message
+{
+ public $map;
+
+ /**
+ * Constructor
+ *
+ * @param array|object|string $body string will get decoded (receive), otherwise the body will be encoded (send)
+ * @param array $headers
+ * @param string $command
+ */
+ public function __construct($body, array $headers = [], $command = 'SEND')
+ {
+ if (is_string($body)) {
+ parent::__construct($body, $headers);
+ $this->command = $command;
+ $this->map = json_decode($body, true);
+ } else {
+ parent::__construct(json_encode($body), $headers + ['transformation' => 'jms-map-json']);
+ $this->command = $command;
+ $this->map = $body;
+ }
+ }
+
+ /**
+ * Returns the received decoded json.
+ *
+ * @return mixed
+ */
+ public function getMap()
+ {
+ return $this->map;
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Transport;
+
+/**
+ * Basic text stomp message
+ *
+ * @package Stomp
+ */
+class Message extends Frame
+{
+ /**
+ * Message constructor.
+ *
+ * @param string $body
+ * @param array $headers
+ */
+ public function __construct($body, array $headers = [])
+ {
+ parent::__construct('SEND', $headers, $body);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Transport;
+
+use Stomp\Network\Observer\ConnectionObserver;
+
+/**
+ * A Stomp frame parser
+ *
+ * @package Stomp
+ * @author Hiram Chirino <hiram@hiramchirino.com>
+ * @author Dejan Bosanac <dejan@nighttale.net>
+ * @author Michael Caplan <mcaplan@labnet.net>
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class Parser
+{
+
+ /**
+ * Frame end
+ */
+ const FRAME_END = "\x00";
+
+ /**
+ * Frame that has been parsed last.
+ *
+ * @var Frame|null
+ */
+ private $frame;
+
+ /**
+ * Active Frame command
+ *
+ * @var string
+ */
+ private $command;
+
+ /**
+ * Active Frame headers
+ *
+ * @var array
+ */
+ private $headers = [];
+
+ /**
+ * Active Frame expected body size (content-length header)
+ *
+ * @var integer|null
+ */
+ private $expectedBodyLength;
+
+ /**
+ * Parser mode
+ *
+ * @var string
+ */
+ private $mode = self::MODE_HEADER;
+
+ /**
+ * Expecting header data mode
+ */
+ const MODE_HEADER = 'HEADER';
+
+ /**
+ * Expecting body end marker mode
+ */
+ const MODE_BODY = 'BODY';
+
+ /**
+ * Header end marker CR_LF
+ */
+ const HEADER_STOP_CR_LF = "\r\n\r\n";
+
+ /**
+ * Header end marker LF
+ */
+ const HEADER_STOP_LF = "\n\n";
+
+ /**
+ * Parser offset within buffer
+ *
+ * @var int
+ */
+ private $offset = 0;
+
+ /**
+ * Buffer size
+ *
+ * @var int
+ */
+ private $bufferSize;
+
+ /**
+ * Current buffer for new frames.
+ *
+ * @var string
+ */
+ private $buffer = '';
+
+ /**
+ * Parser is in stomp 1.0 mode
+ *
+ * @var bool
+ */
+ private $legacyMode = false;
+
+ /**
+ * @var FrameFactory
+ */
+ private $factory;
+
+ /**
+ * @var ConnectionObserver|null
+ */
+ private $observer;
+
+ /**
+ * Parser constructor.
+ *
+ * @param FrameFactory $factory
+ */
+ public function __construct(FrameFactory $factory = null)
+ {
+ $this->factory = $factory ?: new FrameFactory();
+ }
+
+ /**
+ * Sets the observer for the parser, in order to receive heartbeat information.
+ *
+ * @param ConnectionObserver $observer
+ * @return Parser
+ */
+ public function setObserver(ConnectionObserver $observer)
+ {
+ $this->observer = $observer;
+ return $this;
+ }
+
+
+ /**
+ * Returns the factory that will be used to create frame instances.
+ *
+ * @return FrameFactory
+ */
+ public function getFactory()
+ {
+ return $this->factory;
+ }
+
+ /**
+ * Set parser in legacy mode.
+ *
+ * @param bool|false $legacy
+ */
+ public function legacyMode($legacy = false)
+ {
+ $this->legacyMode = $legacy;
+ }
+
+ /**
+ * Add data to parse.
+ *
+ * @param string $data
+ * @return void
+ */
+ public function addData($data)
+ {
+ $this->buffer .= $data;
+ }
+
+ /**
+ * Get next parsed frame.
+ *
+ * @deprecated Will be removed in next version. Please use nextFrame().
+ * @return Frame
+ */
+ public function getFrame()
+ {
+ return $this->frame;
+ }
+
+ /**
+ * Parse current buffer and return the next available frame, otherwise return null.
+ *
+ * @return null|Frame
+ */
+ public function nextFrame()
+ {
+ if ($this->parse()) {
+ $frame = $this->getFrame();
+ $this->frame = null;
+ if ($this->observer) {
+ $this->observer->receivedFrame($frame);
+ }
+ return $frame;
+ }
+ return null;
+ }
+
+
+ /**
+ * Parse current buffer for frames.
+ *
+ * @deprecated Will become private in next version. Please use nextFrame().
+ *
+ * @return bool
+ */
+ public function parse()
+ {
+ if ($this->buffer === '') {
+ return false;
+ }
+ $this->frame = null;
+ $this->offset = 0;
+ $this->bufferSize = strlen($this->buffer);
+ while ($this->offset < $this->bufferSize) {
+ if ($this->mode === self::MODE_HEADER) {
+ $this->skipEmptyLines();
+ if ($this->detectFrameHead()) {
+ $this->mode = self::MODE_BODY;
+ } else {
+ break;
+ }
+ }
+ if ($this->detectFrameEnd()) {
+ $this->mode = self::MODE_HEADER;
+ }
+ break;
+ }
+
+ if ($this->offset > 0) {
+ // remove parsed buffer
+ $this->buffer = substr($this->buffer, $this->offset);
+ }
+ return $this->frame !== null;
+ }
+
+ /**
+ * Skips empty lines before frame headers (they are allowed after \00)
+ */
+ private function skipEmptyLines()
+ {
+ $foundHeartbeat = false;
+ while ($this->offset < $this->bufferSize) {
+ $char = substr($this->buffer, $this->offset, 1);
+ if ($char === "\x00" || $char === "\n" || $char === "\r") {
+ $this->offset++;
+ $foundHeartbeat = true;
+ } else {
+ break;
+ }
+ }
+ if ($foundHeartbeat && $this->observer) {
+ $this->observer->emptyLineReceived();
+ }
+ }
+
+ /**
+ * Detect frame header end marker, starting from current offset.
+ *
+ * @return bool
+ */
+ private function detectFrameHead()
+ {
+ $firstCrLf = strpos($this->buffer, self::HEADER_STOP_CR_LF, $this->offset);
+ $firstLf = strpos($this->buffer, self::HEADER_STOP_LF, $this->offset);
+
+ // we need to use the first available marker, so we need to make sure that cr lf don't overrule lf
+ if ($firstCrLf !== false && ($firstLf === false || $firstLf > $firstCrLf)) {
+ $this->extractFrameMeta(substr($this->buffer, $this->offset, $firstCrLf - $this->offset));
+ $this->offset = $firstCrLf + strlen(self::HEADER_STOP_CR_LF);
+ return true;
+ }
+
+ if ($firstLf !== false) {
+ $this->extractFrameMeta(substr($this->buffer, $this->offset, $firstLf - $this->offset));
+ $this->offset = $firstLf + strlen(self::HEADER_STOP_LF);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Detect frame end marker, starting from current offset.
+ *
+ * @return bool
+ */
+ private function detectFrameEnd()
+ {
+ $bodySize = null;
+ if ($this->expectedBodyLength) {
+ if (($this->bufferSize - $this->offset) >= $this->expectedBodyLength) {
+ $bodySize = $this->expectedBodyLength;
+ }
+ } elseif (($frameEnd = strpos($this->buffer, self::FRAME_END, $this->offset)) !== false) {
+ $bodySize = $frameEnd - $this->offset;
+ }
+
+ if ($bodySize !== null) {
+ $this->setFrame($bodySize);
+ $this->offset += $bodySize + strlen(self::FRAME_END); // x00
+ }
+ return $bodySize !== null;
+ }
+
+
+ /**
+ * Adds a frame from current known command, headers. Uses current offset and given body size.
+ *
+ * @param integer $bodySize
+ */
+ private function setFrame($bodySize)
+ {
+ $this->frame = $this->factory->createFrame(
+ $this->command,
+ $this->headers,
+ (string)substr($this->buffer, $this->offset, $bodySize),
+ $this->legacyMode
+ );
+
+ $this->expectedBodyLength = null;
+ $this->headers = [];
+ $this->mode = self::MODE_HEADER;
+ }
+
+
+ /**
+ * Extracts command and headers from given header source.
+ *
+ * @param string $source
+ * @return void
+ */
+ private function extractFrameMeta($source)
+ {
+ $headers = preg_split("/(\r?\n)+/", $source);
+
+ $this->command = array_shift($headers);
+
+ foreach ($headers as $header) {
+ $headerDetails = explode(':', $header, 2);
+ $name = $this->decodeHeaderValue($headerDetails[0]);
+ $value = isset($headerDetails[1]) ? $this->decodeHeaderValue($headerDetails[1]) : true;
+ if (!isset($this->headers[$name])) {
+ $this->headers[$name] = $value;
+ }
+ }
+
+ if (isset($this->headers['content-length'])) {
+ $this->expectedBodyLength = (int)$this->headers['content-length'];
+ }
+ }
+
+ /**
+ * Decodes header values.
+ *
+ * @param string $value
+ * @return string
+ */
+ private function decodeHeaderValue($value)
+ {
+ if ($this->legacyMode) {
+ return str_replace(['\n'], ["\n"], $value);
+ }
+ return str_replace(['\r', '\n', '\c', "\\\\"], ["\r", "\n", ':', "\\"], $value);
+ }
+
+ /**
+ * Resets the current buffer within this parser and returns the flushed buffer value.
+ *
+ * @return string
+ */
+ public function flushBuffer()
+ {
+ $this->expectedBodyLength = null;
+ $this->headers = [];
+ $this->mode = self::MODE_HEADER;
+
+ $currentBuffer = substr($this->buffer, $this->offset);
+ $this->offset = 0;
+ $this->bufferSize = 0;
+ $this->buffer = '';
+ return $currentBuffer;
+ }
+}
--- /dev/null
+<?php
+/*
+ * This file is part of the Stomp package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Stomp\Util;
+
+/**
+ * IdGenerator generates Ids which are unique during the runtime scope.
+ *
+ * @package Stomp\Util
+ * @author Jens Radtke <swefl.oss@fin-sn.de>
+ */
+class IdGenerator
+{
+ /**
+ * @var array
+ */
+ private static $generatedIds = [];
+
+ /**
+ * Generate a not used id.
+ *
+ * @return int
+ */
+ public static function generateId()
+ {
+ while ($rand = rand(1, PHP_INT_MAX)) {
+ if (!in_array($rand, static::$generatedIds, true)) {
+ static::$generatedIds[] = $rand;
+ return $rand;
+ }
+ }
+ }
+
+ /**
+ * Removes a previous generated id from currently used ids.
+ *
+ * @param int $generatedId
+ */
+ public static function releaseId($generatedId)
+ {
+ $index = array_search($generatedId, static::$generatedIds, true);
+ if ($index !== false) {
+ unset(static::$generatedIds[$index]);
+ }
+ }
+}
+++ /dev/null
-Copyright (c) 2018-2019 Fabien Potencier
-
-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.
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Contracts\Translation;
-
-interface LocaleAwareInterface
-{
- /**
- * Sets the current locale.
- *
- * @param string $locale The locale
- *
- * @throws \InvalidArgumentException If the locale contains invalid characters
- */
- public function setLocale($locale);
-
- /**
- * Returns the current locale.
- *
- * @return string The locale
- */
- public function getLocale();
-}
+++ /dev/null
-Symfony Translation Contracts
-=============================
-
-A set of abstractions extracted out of the Symfony components.
-
-Can be used to build on semantics that the Symfony components proved useful - and
-that already have battle tested implementations.
-
-See https://github.com/symfony/contracts/blob/master/README.md for more information.
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Contracts\Translation\Test;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Contracts\Translation\TranslatorInterface;
-use Symfony\Contracts\Translation\TranslatorTrait;
-
-/**
- * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
- * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms.
- *
- * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
- * The mozilla code is also interesting to check for.
- *
- * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
- *
- * The goal to cover all languages is to far fetched so this test case is smaller.
- *
- * @author Clemens Tolboom clemens@build2be.nl
- */
-class TranslatorTest extends TestCase
-{
- public function getTranslator()
- {
- return new class() implements TranslatorInterface {
- use TranslatorTrait;
- };
- }
-
- /**
- * @dataProvider getTransTests
- */
- public function testTrans($expected, $id, $parameters)
- {
- $translator = $this->getTranslator();
-
- $this->assertEquals($expected, $translator->trans($id, $parameters));
- }
-
- /**
- * @dataProvider getTransChoiceTests
- */
- public function testTransChoiceWithExplicitLocale($expected, $id, $number)
- {
- $translator = $this->getTranslator();
- $translator->setLocale('en');
-
- $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
- }
-
- /**
- * @dataProvider getTransChoiceTests
- */
- public function testTransChoiceWithDefaultLocale($expected, $id, $number)
- {
- \Locale::setDefault('en');
-
- $translator = $this->getTranslator();
-
- $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
- }
-
- public function testGetSetLocale()
- {
- $translator = $this->getTranslator();
- $translator->setLocale('en');
-
- $this->assertEquals('en', $translator->getLocale());
- }
-
- /**
- * @requires extension intl
- */
- public function testGetLocaleReturnsDefaultLocaleIfNotSet()
- {
- $translator = $this->getTranslator();
-
- \Locale::setDefault('pt_BR');
- $this->assertEquals('pt_BR', $translator->getLocale());
-
- \Locale::setDefault('en');
- $this->assertEquals('en', $translator->getLocale());
- }
-
- public function getTransTests()
- {
- return [
- ['Symfony is great!', 'Symfony is great!', []],
- ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']],
- ];
- }
-
- public function getTransChoiceTests()
- {
- return [
- ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
- ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
- ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
- ['There are 0 apples', 'There is 1 apple|There are %count% apples', 0],
- ['There is 1 apple', 'There is 1 apple|There are %count% apples', 1],
- ['There are 10 apples', 'There is 1 apple|There are %count% apples', 10],
- // custom validation messages may be coded with a fixed value
- ['There are 2 apples', 'There are 2 apples', 2],
- ];
- }
-
- /**
- * @dataProvider getInternal
- */
- public function testInterval($expected, $number, $interval)
- {
- $translator = $this->getTranslator();
-
- $this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number]));
- }
-
- public function getInternal()
- {
- return [
- ['foo', 3, '{1,2, 3 ,4}'],
- ['bar', 10, '{1,2, 3 ,4}'],
- ['bar', 3, '[1,2]'],
- ['foo', 1, '[1,2]'],
- ['foo', 2, '[1,2]'],
- ['bar', 1, ']1,2['],
- ['bar', 2, ']1,2['],
- ['foo', log(0), '[-Inf,2['],
- ['foo', -log(0), '[-2,+Inf]'],
- ];
- }
-
- /**
- * @dataProvider getChooseTests
- */
- public function testChoose($expected, $id, $number)
- {
- $translator = $this->getTranslator();
-
- $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
- }
-
- public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
- {
- $translator = $this->getTranslator();
-
- $this->assertEquals('There are two apples', $translator->trans('There are two apples', ['%count%' => 2]));
- }
-
- /**
- * @dataProvider getNonMatchingMessages
- * @expectedException \InvalidArgumentException
- */
- public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
- {
- $translator = $this->getTranslator();
-
- $translator->trans($id, ['%count%' => $number]);
- }
-
- public function getNonMatchingMessages()
- {
- return [
- ['{0} There are no apples|{1} There is one apple', 2],
- ['{1} There is one apple|]1,Inf] There are %count% apples', 0],
- ['{1} There is one apple|]2,Inf] There are %count% apples', 2],
- ['{0} There are no apples|There is one apple', 2],
- ];
- }
-
- public function getChooseTests()
- {
- return [
- ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
- ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
- ['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
-
- ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
-
- ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
- ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10],
- ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
-
- ['There are 0 apples', 'There is one apple|There are %count% apples', 0],
- ['There is one apple', 'There is one apple|There are %count% apples', 1],
- ['There are 10 apples', 'There is one apple|There are %count% apples', 10],
-
- ['There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0],
- ['There is one apple', 'one: There is one apple|more: There are %count% apples', 1],
- ['There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10],
-
- ['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0],
- ['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1],
- ['There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10],
-
- ['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0],
- ['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1],
-
- // Indexed only tests which are Gettext PoFile* compatible strings.
- ['There are 0 apples', 'There is one apple|There are %count% apples', 0],
- ['There is one apple', 'There is one apple|There are %count% apples', 1],
- ['There are 2 apples', 'There is one apple|There are %count% apples', 2],
-
- // Tests for float numbers
- ['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7],
- ['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1],
- ['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7],
- ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
- ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0],
- ['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
-
- // Test texts with new-lines
- // with double-quotes and \n in id & double-quotes and actual newlines in text
- ["This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a
- new-line in it. Selector = 0.|{1}This is a text with a
- new-line in it. Selector = 1.|[1,Inf]This is a text with a
- new-line in it. Selector > 1.', 0],
- // with double-quotes and \n in id and single-quotes and actual newlines in text
- ["This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a
- new-line in it. Selector = 0.|{1}This is a text with a
- new-line in it. Selector = 1.|[1,Inf]This is a text with a
- new-line in it. Selector > 1.', 1],
- ["This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a
- new-line in it. Selector = 0.|{1}This is a text with a
- new-line in it. Selector = 1.|[1,Inf]This is a text with a
- new-line in it. Selector > 1.', 5],
- // with double-quotes and id split accros lines
- ['This is a text with a
- new-line in it. Selector = 1.', '{0}This is a text with a
- new-line in it. Selector = 0.|{1}This is a text with a
- new-line in it. Selector = 1.|[1,Inf]This is a text with a
- new-line in it. Selector > 1.', 1],
- // with single-quotes and id split accros lines
- ['This is a text with a
- new-line in it. Selector > 1.', '{0}This is a text with a
- new-line in it. Selector = 0.|{1}This is a text with a
- new-line in it. Selector = 1.|[1,Inf]This is a text with a
- new-line in it. Selector > 1.', 5],
- // with single-quotes and \n in text
- ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0],
- // with double-quotes and id split accros lines
- ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1],
- // esacape pipe
- ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0],
- // Empty plural set (2 plural forms) from a .PO file
- ['', '|', 1],
- // Empty plural set (3 plural forms) from a .PO file
- ['', '||', 1],
- ];
- }
-
- /**
- * @dataProvider failingLangcodes
- */
- public function testFailedLangcodes($nplural, $langCodes)
- {
- $matrix = $this->generateTestData($langCodes);
- $this->validateMatrix($nplural, $matrix, false);
- }
-
- /**
- * @dataProvider successLangcodes
- */
- public function testLangcodes($nplural, $langCodes)
- {
- $matrix = $this->generateTestData($langCodes);
- $this->validateMatrix($nplural, $matrix);
- }
-
- /**
- * This array should contain all currently known langcodes.
- *
- * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
- *
- * @return array
- */
- public function successLangcodes()
- {
- return [
- ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']],
- ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM']],
- ['3', ['be', 'bs', 'cs', 'hr']],
- ['4', ['cy', 'mt', 'sl']],
- ['6', ['ar']],
- ];
- }
-
- /**
- * This array should be at least empty within the near future.
- *
- * This both depends on a complete list trying to add above as understanding
- * the plural rules of the current failing languages.
- *
- * @return array with nplural together with langcodes
- */
- public function failingLangcodes()
- {
- return [
- ['1', ['fa']],
- ['2', ['jbo']],
- ['3', ['cbs']],
- ['4', ['gd', 'kw']],
- ['5', ['ga']],
- ];
- }
-
- /**
- * We validate only on the plural coverage. Thus the real rules is not tested.
- *
- * @param string $nplural Plural expected
- * @param array $matrix Containing langcodes and their plural index values
- * @param bool $expectSuccess
- */
- protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
- {
- foreach ($matrix as $langCode => $data) {
- $indexes = array_flip($data);
- if ($expectSuccess) {
- $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
- } else {
- $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
- }
- }
- }
-
- protected function generateTestData($langCodes)
- {
- $translator = new class() {
- use TranslatorTrait {
- getPluralizationRule as public;
- }
- };
-
- $matrix = [];
- foreach ($langCodes as $langCode) {
- for ($count = 0; $count < 200; ++$count) {
- $plural = $translator->getPluralizationRule($count, $langCode);
- $matrix[$langCode][$count] = $plural;
- }
- }
-
- return $matrix;
- }
-}
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Contracts\Translation;
-
-/**
- * @author Fabien Potencier <fabien@symfony.com>
- */
-interface TranslatorInterface
-{
- /**
- * Translates the given message.
- *
- * When a number is provided as a parameter named "%count%", the message is parsed for plural
- * forms and a translation is chosen according to this number using the following rules:
- *
- * Given a message with different plural translations separated by a
- * pipe (|), this method returns the correct portion of the message based
- * on the given number, locale and the pluralization rules in the message
- * itself.
- *
- * The message supports two different types of pluralization rules:
- *
- * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
- * indexed: There is one apple|There are %count% apples
- *
- * The indexed solution can also contain labels (e.g. one: There is one apple).
- * This is purely for making the translations more clear - it does not
- * affect the functionality.
- *
- * The two methods can also be mixed:
- * {0} There are no apples|one: There is one apple|more: There are %count% apples
- *
- * An interval can represent a finite set of numbers:
- * {1,2,3,4}
- *
- * An interval can represent numbers between two numbers:
- * [1, +Inf]
- * ]-1,2[
- *
- * The left delimiter can be [ (inclusive) or ] (exclusive).
- * The right delimiter can be [ (exclusive) or ] (inclusive).
- * Beside numbers, you can use -Inf and +Inf for the infinite.
- *
- * @see https://en.wikipedia.org/wiki/ISO_31-11
- *
- * @param string $id The message id (may also be an object that can be cast to string)
- * @param array $parameters An array of parameters for the message
- * @param string|null $domain The domain for the message or null to use the default
- * @param string|null $locale The locale or null to use the default
- *
- * @return string The translated string
- *
- * @throws \InvalidArgumentException If the locale contains invalid characters
- */
- public function trans($id, array $parameters = [], $domain = null, $locale = null);
-}
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Contracts\Translation;
-
-use Symfony\Component\Translation\Exception\InvalidArgumentException;
-
-/**
- * A trait to help implement TranslatorInterface and LocaleAwareInterface.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- */
-trait TranslatorTrait
-{
- private $locale;
-
- /**
- * {@inheritdoc}
- */
- public function setLocale($locale)
- {
- $this->locale = (string) $locale;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getLocale()
- {
- return $this->locale ?: \Locale::getDefault();
- }
-
- /**
- * {@inheritdoc}
- */
- public function trans($id, array $parameters = [], $domain = null, $locale = null)
- {
- $id = (string) $id;
-
- if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
- return strtr($id, $parameters);
- }
-
- $number = (float) $parameters['%count%'];
- $locale = (string) $locale ?: $this->getLocale();
-
- $parts = [];
- if (preg_match('/^\|++$/', $id)) {
- $parts = explode('|', $id);
- } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
- $parts = $matches[0];
- }
-
- $intervalRegexp = <<<'EOF'
-/^(?P<interval>
- ({\s*
- (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
- \s*})
-
- |
-
- (?P<left_delimiter>[\[\]])
- \s*
- (?P<left>-Inf|\-?\d+(\.\d+)?)
- \s*,\s*
- (?P<right>\+?Inf|\-?\d+(\.\d+)?)
- \s*
- (?P<right_delimiter>[\[\]])
-)\s*(?P<message>.*?)$/xs
-EOF;
-
- $standardRules = [];
- foreach ($parts as $part) {
- $part = trim(str_replace('||', '|', $part));
-
- // try to match an explicit rule, then fallback to the standard ones
- if (preg_match($intervalRegexp, $part, $matches)) {
- if ($matches[2]) {
- foreach (explode(',', $matches[3]) as $n) {
- if ($number == $n) {
- return strtr($matches['message'], $parameters);
- }
- }
- } else {
- $leftNumber = '-Inf' === $matches['left'] ? -INF : (float) $matches['left'];
- $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : INF;
-
- if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
- && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
- ) {
- return strtr($matches['message'], $parameters);
- }
- }
- } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
- $standardRules[] = $matches[1];
- } else {
- $standardRules[] = $part;
- }
- }
-
- $position = $this->getPluralizationRule($number, $locale);
-
- if (!isset($standardRules[$position])) {
- // when there's exactly one rule given, and that rule is a standard
- // rule, use this rule
- if (1 === \count($parts) && isset($standardRules[0])) {
- return strtr($standardRules[0], $parameters);
- }
-
- $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
-
- if (class_exists(InvalidArgumentException::class)) {
- throw new InvalidArgumentException($message);
- }
-
- throw new \InvalidArgumentException($message);
- }
-
- return strtr($standardRules[$position], $parameters);
- }
-
- /**
- * Returns the plural position to use for the given locale and number.
- *
- * The plural rules are derived from code of the Zend Framework (2010-09-25),
- * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
- * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- */
- private function getPluralizationRule(int $number, string $locale): int
- {
- switch ('pt_BR' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
- case 'af':
- case 'bn':
- case 'bg':
- case 'ca':
- case 'da':
- case 'de':
- case 'el':
- case 'en':
- case 'eo':
- case 'es':
- case 'et':
- case 'eu':
- case 'fa':
- case 'fi':
- case 'fo':
- case 'fur':
- case 'fy':
- case 'gl':
- case 'gu':
- case 'ha':
- case 'he':
- case 'hu':
- case 'is':
- case 'it':
- case 'ku':
- case 'lb':
- case 'ml':
- case 'mn':
- case 'mr':
- case 'nah':
- case 'nb':
- case 'ne':
- case 'nl':
- case 'nn':
- case 'no':
- case 'oc':
- case 'om':
- case 'or':
- case 'pa':
- case 'pap':
- case 'ps':
- case 'pt':
- case 'so':
- case 'sq':
- case 'sv':
- case 'sw':
- case 'ta':
- case 'te':
- case 'tk':
- case 'ur':
- case 'zu':
- return (1 == $number) ? 0 : 1;
-
- case 'am':
- case 'bh':
- case 'fil':
- case 'fr':
- case 'gun':
- case 'hi':
- case 'hy':
- case 'ln':
- case 'mg':
- case 'nso':
- case 'pt_BR':
- case 'ti':
- case 'wa':
- return ((0 == $number) || (1 == $number)) ? 0 : 1;
-
- case 'be':
- case 'bs':
- case 'hr':
- case 'ru':
- case 'sh':
- case 'sr':
- case 'uk':
- return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
-
- case 'cs':
- case 'sk':
- return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
-
- case 'ga':
- return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2);
-
- case 'lt':
- return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
-
- case 'sl':
- return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3));
-
- case 'mk':
- return (1 == $number % 10) ? 0 : 1;
-
- case 'mt':
- return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
-
- case 'lv':
- return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2);
-
- case 'pl':
- return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
-
- case 'cy':
- return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3));
-
- case 'ro':
- return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
-
- case 'ar':
- return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
-
- default:
- return 0;
- }
- }
-}
+++ /dev/null
-{
- "name": "symfony/translation-contracts",
- "type": "library",
- "description": "Generic abstractions related to translation",
- "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
- "homepage": "https://symfony.com",
- "license": "MIT",
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "require": {
- "php": "^7.1.3"
- },
- "suggest": {
- "symfony/translation-implementation": ""
- },
- "autoload": {
- "psr-4": { "Symfony\\Contracts\\Translation\\": "" }
- },
- "minimum-stability": "dev",
- "extra": {
- "branch-alias": {
- "dev-master": "1.1-dev"
- }
- }
-}